1 package org.opentrafficsim.road.gtu.tactical.lmrs;
2
3 import org.djunits.value.vdouble.scalar.Acceleration;
4 import org.djutils.immutablecollections.ImmutableLinkedHashMap;
5 import org.opentrafficsim.base.parameters.ParameterException;
6 import org.opentrafficsim.base.parameters.ParameterTypeAcceleration;
7 import org.opentrafficsim.base.parameters.ParameterTypeDouble;
8 import org.opentrafficsim.base.parameters.ParameterTypes;
9 import org.opentrafficsim.core.gtu.Stateless;
10 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
11 import org.opentrafficsim.core.network.LateralDirectionality;
12 import org.opentrafficsim.road.gtu.perception.RelativeLane;
13 import org.opentrafficsim.road.gtu.perception.categories.InfrastructurePerception;
14 import org.opentrafficsim.road.gtu.perception.categories.neighbors.NeighborsPerception;
15 import org.opentrafficsim.road.gtu.perception.object.PerceivedGtu;
16 import org.opentrafficsim.road.gtu.tactical.TacticalContextEgo;
17 import org.opentrafficsim.road.gtu.tactical.util.CarFollowingUtil;
18 import org.opentrafficsim.road.gtu.tactical.util.lmrs.Desire;
19 import org.opentrafficsim.road.gtu.tactical.util.lmrs.LmrsParameters;
20 import org.opentrafficsim.road.gtu.tactical.util.lmrs.LmrsUtil;
21 import org.opentrafficsim.road.gtu.tactical.util.lmrs.VoluntaryIncentive;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 public final class IncentiveCourtesy implements VoluntaryIncentive, Stateless<IncentiveCourtesy>
37 {
38
39
40 protected static final ParameterTypeAcceleration B = ParameterTypes.B;
41
42
43 protected static final ParameterTypeDouble SOCIO = LmrsParameters.SOCIO;
44
45
46 public static final IncentiveCourtesy SINGLETON = new IncentiveCourtesy();
47
48 @Override
49 public IncentiveCourtesy get()
50 {
51 return SINGLETON;
52 }
53
54
55
56
57 private IncentiveCourtesy()
58 {
59
60 }
61
62 @Override
63 public Desire determineDesire(final TacticalContextEgo context, final Desire mandatoryDesire,
64 final ImmutableLinkedHashMap<Class<? extends VoluntaryIncentive>, Desire> voluntaryDesire)
65 throws ParameterException, OperationalPlanException
66 {
67 double dLeftYes = 0;
68 double dRightYes = 0;
69 double dLeftNo = 0;
70 double dRightNo = 0;
71 double socio = context.getParameters().getParameter(SOCIO);
72 Acceleration b = context.getParameters().getParameter(B);
73 NeighborsPerception neighbors = context.getPerception().getPerceptionCategory(NeighborsPerception.class);
74 InfrastructurePerception infra = context.getPerception().getPerceptionCategory(InfrastructurePerception.class);
75 boolean leftLane = infra.getLegalLaneChangePossibility(RelativeLane.CURRENT, LateralDirectionality.LEFT).si > 0.0;
76 boolean rightLane = infra.getLegalLaneChangePossibility(RelativeLane.CURRENT, LateralDirectionality.RIGHT).si > 0.0;
77 for (LateralDirectionality dir : LateralDirectionality.LEFT_AND_RIGHT)
78 {
79 Iterable<PerceivedGtu> leaders = neighbors.getLeaders(new RelativeLane(dir, 1));
80 if (leaders != null)
81 {
82 for (PerceivedGtu leader : leaders)
83 {
84 double desire = dir.isLeft() ? leader.getBehavior().rightLaneChangeDesire()
85 : leader.getBehavior().leftLaneChangeDesire();
86 if (desire > 0)
87 {
88
89 Acceleration a = CarFollowingUtil.followSingleLeader(context, leader);
90 if (a.lt0())
91 {
92 double d = desire * Math.min(-a.si / b.si, 1.0);
93 if (dir.isLeft() && rightLane)
94 {
95
96 dRightYes = dRightYes > d ? dRightYes : d;
97 }
98 else if (leftLane)
99 {
100
101 dLeftYes = dLeftYes > d ? dLeftYes : d;
102 }
103 }
104 }
105 }
106 }
107
108 Iterable<PerceivedGtu> followers = neighbors.getFollowers(new RelativeLane(dir, 2));
109 if (followers != null)
110 {
111 for (PerceivedGtu follower : followers)
112 {
113 double desire = dir.isLeft() ? follower.getBehavior().rightLaneChangeDesire()
114 : follower.getBehavior().leftLaneChangeDesire();
115 Acceleration a = follower.getDistance().lt0() ? b.neg()
116 : LmrsUtil.singleAcceleration(follower, follower.getDistance(), context.getSpeed(), desire);
117 if (a.lt0())
118 {
119 if (desire > 0)
120 {
121 double d = desire * Math.min(-a.si / b.si, 1.0);
122 if (dir.isLeft() && leftLane)
123 {
124
125 dLeftNo = dLeftNo > d ? dLeftNo : d;
126 }
127 else if (rightLane)
128 {
129
130 dRightNo = dRightNo > d ? dRightNo : d;
131 }
132 }
133 }
134 else
135 {
136
137 break;
138 }
139 }
140 }
141 leaders = neighbors.getLeaders(new RelativeLane(dir, 2));
142 if (leaders != null)
143 {
144 for (PerceivedGtu leader : leaders)
145 {
146 double desire = dir.isLeft() ? leader.getBehavior().rightLaneChangeDesire()
147 : leader.getBehavior().leftLaneChangeDesire();
148 if (desire > 0)
149 {
150 Acceleration a = LmrsUtil.singleAcceleration(context, leader.getDistance(), leader.getSpeed(), desire);
151 if (a.lt0())
152 {
153 double d = desire * Math.min(-a.si / b.si, 1.0);
154 if (dir.isLeft() && leftLane)
155 {
156
157 dLeftNo = dLeftNo > d ? dLeftNo : d;
158 }
159 else if (rightLane)
160 {
161
162 dRightNo = dRightNo > d ? dRightNo : d;
163 }
164 }
165 }
166 }
167 }
168 }
169
170 dLeftYes *= socio;
171 dRightYes *= socio;
172 return new Desire(dLeftYes - dLeftNo, dRightYes - dRightNo);
173
174 }
175
176 @Override
177 public String toString()
178 {
179 return "IncentiveCourtesy";
180 }
181
182 }