1 package org.opentrafficsim.road.gtu.tactical.util.lmrs;
2
3 import java.util.SortedSet;
4
5 import org.djunits.value.vdouble.scalar.Acceleration;
6 import org.djunits.value.vdouble.scalar.Length;
7 import org.opentrafficsim.base.NamedConstants;
8 import org.opentrafficsim.base.parameters.ParameterException;
9 import org.opentrafficsim.base.parameters.ParameterTypes;
10 import org.opentrafficsim.base.parameters.Parameters;
11 import org.opentrafficsim.core.gtu.plan.operational.OperationalPlanException;
12 import org.opentrafficsim.core.network.LateralDirectionality;
13 import org.opentrafficsim.road.gtu.perception.RelativeLane;
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
19
20
21
22
23
24
25
26
27
28
29 public interface GapAcceptance extends NamedConstants
30 {
31
32
33 GapAcceptance INFORMED = new GapAcceptance()
34 {
35 @Override
36 public boolean acceptGap(final TacticalContextEgo context, final double desire, final LateralDirectionality lat)
37 throws ParameterException, OperationalPlanException
38 {
39 NeighborsPerception neighbors = context.getPerception().getPerceptionCategory(NeighborsPerception.class);
40 if (neighbors.isGtuAlongside(lat))
41 {
42
43 return false;
44 }
45
46 Acceleration threshold = context.getParameters().getParameter(ParameterTypes.B).times(-desire);
47 if (!acceptEgoAcceleration(context, desire, lat, threshold))
48 {
49 return false;
50 }
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 for (PerceivedGtu follower : neighbors.getFirstFollowers(lat))
67 {
68 if (follower.getSpeed().gt0() || follower.getAcceleration().gt0() || follower.getDistance().si < 1.0)
69 {
70 Acceleration aFollow =
71 LmrsUtil.singleAcceleration(follower, follower.getDistance(), context.getSpeed(), desire);
72 if (threshold.gt(aFollow))
73 {
74 return false;
75 }
76 }
77 }
78
79 if (!acceptLaneChangers(context, lat, threshold))
80 {
81 return false;
82 }
83
84 return true;
85 }
86
87 @Override
88 public String name()
89 {
90 return "INFORMED";
91 }
92 };
93
94
95 GapAcceptance EGO_HEADWAY = new GapAcceptance()
96 {
97 @Override
98 public boolean acceptGap(final TacticalContextEgo context, final double desire, final LateralDirectionality lat)
99 throws ParameterException, OperationalPlanException
100 {
101 NeighborsPerception neigbors = context.getPerception().getPerceptionCategory(NeighborsPerception.class);
102 if (neigbors.isGtuAlongside(lat))
103 {
104
105 return false;
106 }
107
108 Acceleration threshold = context.getParameters().getParameter(ParameterTypes.B).times(-desire);
109 if (!acceptEgoAcceleration(context, desire, lat, threshold))
110 {
111 return false;
112 }
113
114 for (PerceivedGtu follower : neigbors.getFirstFollowers(lat))
115 {
116 if (follower.getSpeed().gt0() || follower.getAcceleration().gt0())
117 {
118
119 Parameters folParams = follower.getBehavior().getParameters();
120 folParams.setParameter(ParameterTypes.TMIN, context.getParameters().getParameter(ParameterTypes.TMIN));
121 folParams.setParameter(ParameterTypes.TMAX, context.getParameters().getParameter(ParameterTypes.TMAX));
122 Acceleration aFollow =
123 LmrsUtil.singleAcceleration(follower, follower.getDistance(), context.getSpeed(), desire);
124 folParams.resetParameter(ParameterTypes.TMIN);
125 folParams.resetParameter(ParameterTypes.TMAX);
126 if (threshold.gt(aFollow))
127 {
128 return false;
129 }
130 }
131 }
132
133 if (!acceptLaneChangers(context, lat, threshold))
134 {
135 return false;
136 }
137
138 return true;
139 }
140
141 @Override
142 public String name()
143 {
144 return "EGO_HEADWAY";
145 }
146 };
147
148
149
150
151
152
153
154
155
156
157
158 private static boolean acceptEgoAcceleration(final TacticalContextEgo context, final double desire,
159 final LateralDirectionality lat, final Acceleration threshold) throws ParameterException, OperationalPlanException
160 {
161 if (context.getSpeed().gt0())
162 {
163 for (PerceivedGtu leader : context.getPerception().getPerceptionCategory(NeighborsPerception.class)
164 .getFirstLeaders(lat))
165 {
166 Acceleration a = LmrsUtil.singleAcceleration(context, leader.getDistance(), leader.getSpeed(), desire);
167 if (threshold.gt(a))
168 {
169 return false;
170 }
171 }
172 }
173 return true;
174 }
175
176
177
178
179
180
181
182
183
184
185 private static boolean acceptLaneChangers(final TacticalContextEgo context, final LateralDirectionality lat,
186 final Acceleration threshold) throws ParameterException, OperationalPlanException
187 {
188 if (context.getSpeed().gt0())
189 {
190 NeighborsPerception neighbors = context.getPerception().getPerceptionCategory(NeighborsPerception.class);
191
192 SortedSet<PerceivedGtu> firstLeaders = neighbors.getFirstLeaders(lat);
193 Length range = Length.POS_MAXVALUE;
194 if (!firstLeaders.isEmpty())
195 {
196 range = Length.ZERO;
197 for (PerceivedGtu leader : firstLeaders)
198 {
199 range = Length.max(range, leader.getDistance());
200 }
201 }
202 for (PerceivedGtu leader : neighbors.getLeaders(new RelativeLane(lat, 2)))
203 {
204 if (leader.getDistance().gt(range))
205 {
206 return true;
207 }
208 if (leader.getManeuver().isChangingLane(lat.flip()))
209 {
210 Acceleration a = CarFollowingUtil.followSingleLeader(context, leader.getDistance(), leader.getSpeed());
211 return a.ge(threshold);
212 }
213 }
214 }
215 return true;
216 }
217
218
219
220
221
222
223
224
225
226
227 boolean acceptGap(TacticalContextEgo context, double desire, LateralDirectionality lat)
228 throws ParameterException, OperationalPlanException;
229
230 }