1 package org.opentrafficsim.road.gtu.tactical.lmrs;
2
3 import java.util.LinkedHashMap;
4 import java.util.LinkedHashSet;
5 import java.util.Map;
6 import java.util.Optional;
7
8 import org.djunits.value.vdouble.scalar.Acceleration;
9 import org.djunits.value.vdouble.scalar.Length;
10 import org.djutils.immutablecollections.Immutable;
11 import org.djutils.immutablecollections.ImmutableLinkedHashMap;
12 import org.djutils.immutablecollections.ImmutableLinkedHashSet;
13 import org.djutils.immutablecollections.ImmutableSet;
14 import org.opentrafficsim.base.parameters.ParameterException;
15 import org.opentrafficsim.core.gtu.GtuException;
16 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
17 import org.opentrafficsim.road.gtu.LaneBasedGtu;
18 import org.opentrafficsim.road.gtu.perception.LanePerception;
19 import org.opentrafficsim.road.gtu.perception.RelativeLane;
20 import org.opentrafficsim.road.gtu.tactical.AbstractLaneBasedTacticalPlanner;
21 import org.opentrafficsim.road.gtu.tactical.TacticalContextEgo;
22 import org.opentrafficsim.road.gtu.tactical.following.CarFollowingModel;
23 import org.opentrafficsim.road.gtu.tactical.util.lmrs.Desire;
24 import org.opentrafficsim.road.gtu.tactical.util.lmrs.Incentive;
25 import org.opentrafficsim.road.gtu.tactical.util.lmrs.MandatoryIncentive;
26 import org.opentrafficsim.road.gtu.tactical.util.lmrs.VoluntaryIncentive;
27
28
29
30
31
32
33
34
35
36
37
38
39
40 public abstract class AbstractIncentivesTacticalPlanner extends AbstractLaneBasedTacticalPlanner
41 implements DesireBased, AccelerationBased
42 {
43
44
45 private final LinkedHashSet<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
46
47
48 private final LinkedHashSet<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
49
50
51 private final LinkedHashSet<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
52
53
54 private ImmutableSet<MandatoryIncentive> mandatoryIncentivesImmutable =
55 new ImmutableLinkedHashSet<>(this.mandatoryIncentives, Immutable.WRAP);
56
57
58 private ImmutableSet<VoluntaryIncentive> voluntaryIncentivesImmutable =
59 new ImmutableLinkedHashSet<>(this.voluntaryIncentives, Immutable.WRAP);
60
61
62 private ImmutableSet<AccelerationIncentive> accelerationIncentivesImmutable =
63 new ImmutableLinkedHashSet<>(this.accelerationIncentives, Immutable.WRAP);
64
65
66 private Map<Class<? extends MandatoryIncentive>, Desire> mandatoryDesire = new LinkedHashMap<>();
67
68
69 private Map<Class<? extends VoluntaryIncentive>, Desire> voluntaryDesire = new LinkedHashMap<>();
70
71
72 private Map<Class<? extends AccelerationIncentive>, Acceleration> acceleration = new LinkedHashMap<>();
73
74
75 private ImmutableLinkedHashMap<Class<? extends MandatoryIncentive>, Desire> mandatoryDesireImmutable =
76 new ImmutableLinkedHashMap<>(this.mandatoryDesire, Immutable.WRAP);
77
78
79 private ImmutableLinkedHashMap<Class<? extends VoluntaryIncentive>, Desire> voluntaryDesireImmutable =
80 new ImmutableLinkedHashMap<>(this.voluntaryDesire, Immutable.WRAP);
81
82
83 private Desire mandatory;
84
85
86 private Desire voluntary;
87
88
89
90
91
92
93
94 public AbstractIncentivesTacticalPlanner(final CarFollowingModel carFollowingModel, final LaneBasedGtu gtu,
95 final LanePerception lanePerception)
96 {
97 super(carFollowingModel, gtu, lanePerception);
98 }
99
100
101
102
103
104 public void addMandatoryIncentive(final MandatoryIncentive incentive)
105 {
106 if (incentive != null)
107 {
108 this.mandatoryIncentives.add(incentive);
109 }
110 }
111
112
113
114
115
116 public void addVoluntaryIncentive(final VoluntaryIncentive incentive)
117 {
118 if (incentive != null)
119 {
120 this.voluntaryIncentives.add(incentive);
121 }
122 }
123
124
125
126
127
128 public void addAccelerationIncentive(final AccelerationIncentive incentive)
129 {
130 if (incentive != null)
131 {
132 this.accelerationIncentives.add(incentive);
133 }
134 }
135
136
137
138
139
140 public ImmutableSet<MandatoryIncentive> getMandatoryIncentives()
141 {
142 return this.mandatoryIncentivesImmutable;
143 }
144
145
146
147
148
149 public ImmutableSet<VoluntaryIncentive> getVoluntaryIncentives()
150 {
151 return this.voluntaryIncentivesImmutable;
152 }
153
154
155
156
157
158 public ImmutableSet<AccelerationIncentive> getAccelerationIncentives()
159 {
160 return this.accelerationIncentivesImmutable;
161 }
162
163
164
165
166
167
168
169
170 public Desire getMandatoryDesire(final TacticalContextEgo context) throws OperationalPlanException, ParameterException
171 {
172 double dLeftMandatory = 0.0;
173 double dRightMandatory = 0.0;
174 for (MandatoryIncentive incentive : this.mandatoryIncentives)
175 {
176 Desire d = incentive.determineDesire(context, this.mandatoryDesireImmutable);
177 this.mandatoryDesire.put(incentive.getClass(), d);
178 dLeftMandatory = Math.abs(d.left()) > Math.abs(dLeftMandatory) ? d.left() : dLeftMandatory;
179 dRightMandatory = Math.abs(d.right()) > Math.abs(dRightMandatory) ? d.right() : dRightMandatory;
180 }
181 this.mandatory = new Desire(dLeftMandatory, dRightMandatory);
182 return this.mandatory;
183 }
184
185
186
187
188
189
190
191
192 public Desire getVoluntaryDesire(final TacticalContextEgo context) throws OperationalPlanException, ParameterException
193 {
194 double dLeftVoluntary = 0;
195 double dRightVoluntary = 0;
196 for (VoluntaryIncentive incentive : this.voluntaryIncentives)
197 {
198 Desire d = incentive.determineDesire(context, this.mandatory, this.voluntaryDesireImmutable);
199 this.voluntaryDesire.put(incentive.getClass(), d);
200 dLeftVoluntary += d.left();
201 dRightVoluntary += d.right();
202 }
203 this.voluntary = new Desire(dLeftVoluntary, dRightVoluntary);
204 return this.voluntary;
205 }
206
207
208
209
210
211 public Desire getLatestMandatoryDesire()
212 {
213 return this.mandatory;
214 }
215
216
217
218
219
220 public Desire getLatestVoluntaryDesire()
221 {
222 return this.voluntary;
223 }
224
225 @Override
226 public Optional<Desire> getLatestDesire(final Class<? extends Incentive> incentive)
227 {
228 if (this.voluntaryDesire.containsKey(incentive))
229 {
230 return Optional.ofNullable(this.voluntaryDesire.get(incentive));
231 }
232 return Optional.ofNullable(this.mandatoryDesire.get(incentive));
233 }
234
235
236
237
238
239
240
241
242
243
244 public Acceleration getAcceleration(final TacticalContextEgo context, final RelativeLane lane, final Length mergeDistance)
245 throws ParameterException, GtuException
246 {
247 Acceleration a = Acceleration.POS_MAXVALUE;
248 for (AccelerationIncentive incentive : this.accelerationIncentives)
249 {
250 Acceleration aIncentive = incentive.accelerate(context, lane, mergeDistance);
251 this.acceleration.put(incentive.getClass(), aIncentive);
252 a = Acceleration.min(a, aIncentive);
253 }
254 return a;
255 }
256
257 @Override
258 public Optional<Acceleration> getLatestAcceleration(final Class<? extends AccelerationIncentive> incentiveClass)
259 {
260 return Optional.ofNullable(this.acceleration.get(incentiveClass));
261 }
262
263 }