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