1 package org.opentrafficsim.road.gtu.lane.tactical.lmrs;
2
3 import org.djunits.unit.DimensionlessUnit;
4 import org.djunits.unit.SpeedUnit;
5 import org.djunits.value.vdouble.scalar.Acceleration;
6 import org.djunits.value.vdouble.scalar.Dimensionless;
7 import org.djunits.value.vdouble.scalar.Length;
8 import org.djunits.value.vdouble.scalar.Speed;
9 import org.opentrafficsim.core.gtu.behavioralcharacteristics.AbstractParameterType;
10 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
11 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
12 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypeSpeed;
13 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
14 import org.opentrafficsim.core.gtu.perception.EgoPerception;
15 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
16 import org.opentrafficsim.core.network.LateralDirectionality;
17 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
18 import org.opentrafficsim.road.gtu.lane.perception.RelativeLane;
19 import org.opentrafficsim.road.gtu.lane.perception.categories.InfrastructurePerception;
20 import org.opentrafficsim.road.gtu.lane.perception.categories.NeighborsPerception;
21 import org.opentrafficsim.road.gtu.lane.perception.headway.AbstractHeadwayGTU;
22 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModel;
23 import org.opentrafficsim.road.gtu.lane.tactical.util.CarFollowingUtil;
24 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Desire;
25 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class IncentiveSpeedWithCourtesy implements VoluntaryIncentive
50 {
51
52
53 public static final ParameterTypeSpeed VGAIN = new ParameterTypeSpeed("vGain", "Anticipation speed difference at "
54 + "full lane change desired.", new Speed(69.6, SpeedUnit.KM_PER_HOUR), AbstractParameterType.Check.POSITIVE);
55
56
57 @Override
58 public final Desire determineDesire(final BehavioralCharacteristics behavioralCharacteristics,
59 final LanePerception perception, final CarFollowingModel carFollowingModel, final Desire mandatoryDesire,
60 final Desire voluntaryDesire) throws ParameterException, OperationalPlanException
61 {
62
63
64 if (perception.getPerceptionCategory(InfrastructurePerception.class).getLegalLaneChangePossibility(
65 RelativeLane.CURRENT, LateralDirectionality.LEFT).si == 0
66 && perception.getPerceptionCategory(InfrastructurePerception.class).getLegalLaneChangePossibility(
67 RelativeLane.CURRENT, LateralDirectionality.RIGHT).si == 0)
68 {
69 return new Desire(0, 0);
70 }
71
72
73 Speed vCur = anticipationSpeed(RelativeLane.CURRENT, behavioralCharacteristics, perception, carFollowingModel);
74 Speed vGain = behavioralCharacteristics.getParameter(VGAIN);
75
76
77 Dimensionless aGain;
78 Acceleration aCur =
79 CarFollowingUtil.followLeaders(carFollowingModel, behavioralCharacteristics, perception.getPerceptionCategory(
80 EgoPerception.class).getSpeed(), perception.getPerceptionCategory(InfrastructurePerception.class)
81 .getSpeedLimitProspect(RelativeLane.CURRENT).getSpeedLimitInfo(Length.ZERO), perception
82 .getPerceptionCategory(NeighborsPerception.class).getLeaders(RelativeLane.CURRENT));
83 if (aCur.si > 0)
84 {
85 Acceleration a = behavioralCharacteristics.getParameter(ParameterTypes.A);
86 aGain = a.minus(aCur).divideBy(a);
87 }
88 else
89 {
90 aGain = new Dimensionless(1, DimensionlessUnit.SI);
91 }
92
93
94 Dimensionless dLeft;
95 if (perception.getPerceptionCategory(InfrastructurePerception.class).getCrossSection().contains(RelativeLane.LEFT))
96 {
97 Speed vLeft = anticipationSpeed(RelativeLane.LEFT, behavioralCharacteristics, perception, carFollowingModel);
98 dLeft = aGain.multiplyBy(vLeft.minus(vCur)).divideBy(vGain);
99 }
100 else
101 {
102 dLeft = Dimensionless.ZERO;
103 }
104
105
106 Dimensionless dRight;
107 if (perception.getPerceptionCategory(InfrastructurePerception.class).getCrossSection().contains(RelativeLane.RIGHT))
108 {
109 Speed vRight = anticipationSpeed(RelativeLane.RIGHT, behavioralCharacteristics, perception, carFollowingModel);
110 dRight = aGain.multiplyBy(vRight.minus(vCur)).divideBy(vGain);
111 }
112 else
113 {
114 dRight = Dimensionless.ZERO;
115 }
116
117
118 return new Desire(dLeft, dRight);
119 }
120
121
122
123
124
125
126
127
128
129
130
131 private Speed anticipationSpeed(final RelativeLane lane, final BehavioralCharacteristics bc,
132 final LanePerception perception, final CarFollowingModel cfm) throws ParameterException, OperationalPlanException
133 {
134
135 Speed anticipationSpeed =
136 cfm.desiredSpeed(bc, perception.getPerceptionCategory(InfrastructurePerception.class).getSpeedLimitProspect(lane)
137 .getSpeedLimitInfo(Length.ZERO));
138 Speed desiredSpeed = new Speed(anticipationSpeed);
139 Length x0 = bc.getParameter(ParameterTypes.LOOKAHEAD);
140
141
142 if (perception.getPerceptionCategory(InfrastructurePerception.class).getCrossSection().contains(lane.getLeft()))
143 {
144 for (AbstractHeadwayGTU headwayGTU : perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(
145 lane.getLeft()))
146 {
147
148 if (headwayGTU.isRightTurnIndicatorOn() && !lane.getLeft().equals(RelativeLane.CURRENT))
149 {
150 anticipationSpeed = anticipateSingle(anticipationSpeed, desiredSpeed, x0, headwayGTU);
151 }
152 }
153 }
154
155
156 if (perception.getPerceptionCategory(InfrastructurePerception.class).getCrossSection().contains(lane.getRight()))
157 {
158 for (AbstractHeadwayGTU headwayGTU : perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(
159 lane.getRight()))
160 {
161
162 if (headwayGTU.isLeftTurnIndicatorOn() && !lane.getRight().equals(RelativeLane.CURRENT))
163 {
164 anticipationSpeed = anticipateSingle(anticipationSpeed, desiredSpeed, x0, headwayGTU);
165 }
166 }
167 }
168
169
170 for (AbstractHeadwayGTU headwayGTU : perception.getPerceptionCategory(NeighborsPerception.class).getLeaders(lane))
171 {
172 anticipationSpeed = anticipateSingle(anticipationSpeed, desiredSpeed, x0, headwayGTU);
173 }
174
175 return anticipationSpeed;
176 }
177
178
179
180
181
182
183
184
185
186 private Speed anticipateSingle(final Speed anticipationSpeed, final Speed desiredSpeed, final Length x0,
187 final AbstractHeadwayGTU headwayGTU)
188 {
189 if (headwayGTU.getSpeed().gt(anticipationSpeed) || headwayGTU.getDistance().gt(x0))
190 {
191 return anticipationSpeed;
192 }
193 Speed vSingle = Speed.interpolate(headwayGTU.getSpeed(), desiredSpeed, headwayGTU.getDistance().si / x0.si);
194 return anticipationSpeed.lt(vSingle) ? anticipationSpeed : vSingle;
195 }
196
197
198 @Override
199 public final String toString()
200 {
201 return "IncentiveSpeedWithCourtesy";
202 }
203
204 }