1 package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2
3 import java.util.ArrayList;
4
5 import nl.tudelft.simulation.language.d3.DirectedPoint;
6
7 import org.djunits.unit.AccelerationUnit;
8 import org.djunits.unit.SpeedUnit;
9 import org.djunits.value.vdouble.scalar.Acceleration;
10 import org.djunits.value.vdouble.scalar.Speed;
11 import org.djunits.value.vdouble.scalar.Time.Abs;
12 import org.opentrafficsim.core.gtu.GTU;
13 import org.opentrafficsim.core.gtu.GTUException;
14 import org.opentrafficsim.core.gtu.drivercharacteristics.ParameterException;
15 import org.opentrafficsim.core.gtu.drivercharacteristics.ParameterTypeDouble;
16 import org.opentrafficsim.core.gtu.drivercharacteristics.ParameterTypes;
17 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlan;
18 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
19 import org.opentrafficsim.core.network.NetworkException;
20 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
21 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
22 import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlanner;
23 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
24 import org.opentrafficsim.road.gtu.lane.tactical.following.HeadwayGTU;
25
26
27
28
29
30
31
32
33
34
35
36 public class LMRS extends AbstractLaneBasedTacticalPlanner {
37
38 private static final long serialVersionUID = 20160803L;
39
40
41 public static final ParameterTypeDouble DFREE = new ParameterTypeDouble("dFree",
42 "Free lane change desire threshold.", 0.365) {
43 public void check(double value) throws ParameterException {
44 ParameterException.failIf(value<=0, "Parameter of type dFree may not have a negative or zero value.");
45 ParameterException.failIf(value>1, "Parameter of type dFree may not have a value greater than 1.");
46 }
47 };
48
49
50 public static final ParameterTypeDouble DSYNC = new ParameterTypeDouble("dSync",
51 "Synchronized lane change desire threshold.", 0.577) {
52 public void check(double value) throws ParameterException {
53 ParameterException.failIf(value<=0, "Parameter of type dSync may not have a negative or zero value.");
54 ParameterException.failIf(value>1, "Parameter of type dSync may not have a value greater than 1.");
55 }
56 };
57
58
59 public static final ParameterTypeDouble DCOOP = new ParameterTypeDouble("dCoop",
60 "Cooperative lane change desire threshold.", 0.788) {
61 public void check(double value) throws ParameterException {
62 ParameterException.failIf(value<=0, "Parameter of type dCoop may not have a negative or zero value.");
63 ParameterException.failIf(value>1, "Parameter of type dCoop may not have a value greater than 1.");
64 }
65 };
66
67
68 protected Acceleration minimumAcceleration;
69
70
71 protected ArrayList<MandatoryIncentive> mandatoryIncentives;
72
73
74 protected ArrayList<VoluntaryIncentive> voluntaryIncentives;
75
76
77
78
79
80 public void addMandatoryIncentive(MandatoryIncentive incentive) {
81 this.mandatoryIncentives.add(incentive);
82 }
83
84
85
86
87
88 public void addVoluntaryIncentive(VoluntaryIncentive incentive) {
89 this.voluntaryIncentives.add(incentive);
90 }
91
92
93
94
95
96 public void setDefaultIncentives() {
97 this.mandatoryIncentives.clear();
98 this.voluntaryIncentives.clear();
99 this.mandatoryIncentives.add(new IncentiveRoute());
100 this.voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
101 this.voluntaryIncentives.add(new IncentiveKeep());
102 }
103
104
105
106
107 public void disableLaneChanges() {
108 this.mandatoryIncentives.clear();
109 this.voluntaryIncentives.clear();
110 this.mandatoryIncentives.add(new IncentiveDummy());
111 }
112
113 @Override
114 public OperationalPlan generateOperationalPlan(GTU gtu, Abs startTime, DirectedPoint locationAtStartTime)
115 throws OperationalPlanException, GTUException, NetworkException {
116
117
118
119 Acceleration dummy = new Acceleration(0, AccelerationUnit.SI);
120
121
122 if (mandatoryIncentives.isEmpty()) {
123 throw new OperationalPlanException("At the least the LMRS requires 1 mandatory lane change incentive.");
124 }
125
126
127 LaneBasedGTU gtuLane = (LaneBasedGTU) gtu;
128 LanePerception perception = (LanePerception) gtu.getPerception();
129 CarFollowingModel dfm = (CarFollowingModel) gtuLane.getStrategicalPlanner().getDrivingCharacteristics().getGTUFollowingModel();
130
131
132
133 Acceleration b;
134 double dFree;
135 double dSync;
136 double dCoop;
137 try {
138 b = gtuLane.getBehavioralCharacteristics().getAccelerationParameter(ParameterTypes.B);
139 dFree = gtuLane.getBehavioralCharacteristics().getParameter(DFREE);
140 dSync = gtuLane.getBehavioralCharacteristics().getParameter(DSYNC);
141 dCoop = gtuLane.getBehavioralCharacteristics().getParameter(DCOOP);
142 } catch (ParameterException pe) {
143 throw new RuntimeException(pe);
144 }
145
146
147 minimumAcceleration = new Acceleration(Double.POSITIVE_INFINITY, AccelerationUnit.SI);
148
149
150 if (Math.random()>.5) {
151
152
153
154
155 lowerAcceleration(dummy);
156 lowerAcceleration(dummy);
157
158
159
160
161
162
163 return null;
164
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 double dLeftMandatory = Double.NEGATIVE_INFINITY;
182 double dRightMandatory = Double.NEGATIVE_INFINITY;
183 for (MandatoryIncentive incentive : this.mandatoryIncentives) {
184 Desire d = incentive.determineDesire(gtuLane, perception);
185 dLeftMandatory = d.getLeft()>dLeftMandatory ? d.getLeft() : dLeftMandatory;
186 dRightMandatory = d.getRight()>dRightMandatory ? d.getRight() : dRightMandatory;
187 }
188 Desire mandatoryDesire = new Desire(dLeftMandatory, dRightMandatory);
189
190 double dLeftVoluntary = 0;
191 double dRightVoluntary = 0;
192 for (VoluntaryIncentive incentive : this.voluntaryIncentives) {
193 Desire d = incentive.determineDesire(gtuLane, perception, mandatoryDesire);
194 dLeftVoluntary += d.getLeft();
195 dRightVoluntary += d.getRight();
196 }
197
198 double thetaLeft = 0;
199 if (dLeftMandatory<=dSync || dLeftMandatory*dLeftVoluntary>=0) {
200
201 thetaLeft = 1;
202 } else if (dSync<dLeftMandatory && dLeftMandatory<dCoop && dLeftMandatory*dLeftVoluntary<0) {
203
204 thetaLeft = (dCoop-Math.abs(dLeftMandatory)) / (dCoop-dSync);
205 }
206 double thetaRight = 0;
207 if (dRightMandatory<=dSync || dRightMandatory*dRightVoluntary>=0) {
208
209 thetaRight = 1;
210 } else if (dSync<dRightMandatory && dRightMandatory<dCoop && dRightMandatory*dRightVoluntary<0) {
211
212 thetaRight = (dCoop-Math.abs(dRightMandatory)) / (dCoop-dSync);
213 }
214 Desire totalDesire = new Desire(dLeftMandatory + thetaLeft*dLeftVoluntary,
215 dRightMandatory + thetaRight*dRightVoluntary);
216
217
218
219
220
221
222
223 Acceleration aFollow = dummy;
224 Acceleration aSelf = dummy;
225 boolean leftAllowed = true;
226 boolean acceptLeft = aSelf.getSI()>=-b.si*totalDesire.getLeft() &&
227 aFollow.getSI()>=-b.si*totalDesire.getLeft() && leftAllowed;
228 aFollow = dummy;
229 aSelf = dummy;
230 boolean rightAllowed = true;
231 boolean acceptRight = aSelf.getSI()>=-b.si*totalDesire.getRight() &&
232 aFollow.getSI()>=-b.si*totalDesire.getRight() && rightAllowed;
233
234
235
236
237
238
239
240 boolean changeLeft = false;
241 boolean changeRight = false;
242 if (totalDesire.leftIsLargerOrEqual() && totalDesire.getLeft()>=dFree && acceptLeft) {
243
244 changeLeft = true;
245 } else if (!totalDesire.leftIsLargerOrEqual() && totalDesire.getRight()>=dFree && acceptRight) {
246
247 changeRight = true;
248 } else if (totalDesire.leftIsLargerOrEqual() && totalDesire.getLeft()>=dCoop) {
249
250
251 } else if (!totalDesire.leftIsLargerOrEqual() && totalDesire.getRight()>=dCoop) {
252
253
254 }
255
256
257
258
259
260
261
262 lowerAcceleration(dummy);
263
264
265 if (totalDesire.leftIsLargerOrEqual() && totalDesire.getLeft()>=dSync) {
266
267 lowerAcceleration(safe(dummy, b));
268 } else if (!totalDesire.leftIsLargerOrEqual() && totalDesire.getRight()>=dSync) {
269
270 lowerAcceleration(safe(dummy, b));
271 }
272
273
274 if (Math.random()>0) {
275
276 lowerAcceleration(safe(dummy, b));
277 }
278 if (Math.random()>0) {
279
280 lowerAcceleration(safe(dummy, b));
281 }
282
283
284
285
286
287
288
289 return null;
290
291 }
292
293 protected Acceleration calculateAcceleration(LaneBasedGTU follower, HeadwayGTU leader, double d) {
294
295
296 Acceleration a = calculateAcceleration(follower, leader);
297
298 return a;
299 }
300
301 protected Acceleration calculateAcceleration(LaneBasedGTU follower, HeadwayGTU leader) {
302
303
304 Speed speedLimit = new Speed(0, SpeedUnit.SI);
305 return follower.getStrategicalPlanner().getDrivingCharacteristics().getGTUFollowingModel().computeAcceleration(follower.getVelocity(), follower.getMaximumVelocity(), leader.getGtuSpeed(), leader.getDistance(), speedLimit);
306 }
307
308
309
310
311
312 protected void lowerAcceleration(Acceleration a) {
313 if (a.getSI()<this.minimumAcceleration.si) {
314 this.minimumAcceleration = a;
315 }
316 }
317
318
319
320
321
322
323
324 protected Acceleration safe(Acceleration a, Acceleration b) {
325 if (a.si>=-b.si) {
326 return a;
327 }
328 return new Acceleration(-b.si, AccelerationUnit.SI);
329 }
330
331 }