1 package org.opentrafficsim.road.gtu.generator;
2
3 import java.io.Serializable;
4 import java.util.LinkedList;
5 import java.util.Queue;
6 import java.util.Set;
7
8 import javax.naming.NamingException;
9
10 import org.djunits.unit.AccelerationUnit;
11 import org.djunits.unit.DurationUnit;
12 import org.djunits.unit.LengthUnit;
13 import org.djunits.value.vdouble.scalar.Acceleration;
14 import org.djunits.value.vdouble.scalar.Duration;
15 import org.djunits.value.vdouble.scalar.Length;
16 import org.djunits.value.vdouble.scalar.Speed;
17 import org.djunits.value.vdouble.scalar.Time;
18 import org.opentrafficsim.core.distributions.Generator;
19 import org.opentrafficsim.core.distributions.ProbabilityException;
20 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
21 import org.opentrafficsim.core.geometry.OTSGeometryException;
22 import org.opentrafficsim.core.gtu.GTUDirectionality;
23 import org.opentrafficsim.core.gtu.GTUException;
24 import org.opentrafficsim.core.gtu.GTUType;
25 import org.opentrafficsim.core.gtu.RelativePosition;
26 import org.opentrafficsim.core.gtu.animation.GTUColorer;
27 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
28 import org.opentrafficsim.core.network.NetworkException;
29 import org.opentrafficsim.core.network.OTSNetwork;
30 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
31 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
32 import org.opentrafficsim.road.gtu.lane.LaneBasedGTUCharacteristics;
33 import org.opentrafficsim.road.gtu.lane.LaneBasedGTUCharacteristicsGenerator;
34 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
35 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
36 import org.opentrafficsim.road.network.lane.Lane;
37
38 import nl.tudelft.simulation.dsol.SimRuntimeException;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class LaneBasedGTUGenerator implements Serializable
54 {
55
56 private static final long serialVersionUID = 20160000L;
57
58
59 private final Queue<LaneBasedGTUCharacteristics> unplacedTemplates = new LinkedList<>();
60
61
62 private final String id;
63
64
65 private final Generator<Duration> interarrivelTimeGenerator;
66
67
68 private final LaneBasedGTUCharacteristicsGenerator laneBasedGTUCharacteristicsGenerator;
69
70
71 private final Time endTime;
72
73
74 private final long maxGTUs;
75
76
77 private long generatedGTUs = 0;
78
79
80 Duration reTryInterval = new Duration(0.1, DurationUnit.SI);
81
82
83 final Set<DirectedLanePosition> initialLongitudinalPositions;
84
85
86 final RoomChecker roomChecker;
87
88
89 final GTUColorer gtuColorer;
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 public LaneBasedGTUGenerator(String id, final Generator<Duration> interarrivelTimeGenerator, final long maxGTUs,
111 final Time startTime, final Time endTime, final GTUColorer gtuColorer,
112 final LaneBasedGTUCharacteristicsGenerator laneBasedGTUCharacteristicsGenerator,
113 final Set<DirectedLanePosition> initialLongitudinalPositions, final OTSNetwork network, RoomChecker roomChecker)
114 throws SimRuntimeException, ProbabilityException, ParameterException
115 {
116 this.id = id;
117 this.interarrivelTimeGenerator = interarrivelTimeGenerator;
118 this.laneBasedGTUCharacteristicsGenerator = laneBasedGTUCharacteristicsGenerator;
119 this.endTime = endTime;
120 this.maxGTUs = maxGTUs;
121 this.initialLongitudinalPositions = initialLongitudinalPositions;
122 this.roomChecker = roomChecker;
123 this.gtuColorer = gtuColorer;
124 laneBasedGTUCharacteristicsGenerator.getSimulator().scheduleEventAbs(
125 startTime.plus(this.interarrivelTimeGenerator.draw()), this, this, "generateCharacteristics", new Object[] {});
126 }
127
128
129
130
131
132
133
134
135
136 @SuppressWarnings("unused")
137 private void generateCharacteristics() throws ProbabilityException, SimRuntimeException, ParameterException, GTUException
138 {
139 OTSDEVSSimulatorInterface simulator = this.laneBasedGTUCharacteristicsGenerator.getSimulator();
140 if (this.generatedGTUs >= this.maxGTUs
141 || this.laneBasedGTUCharacteristicsGenerator.getSimulator().getSimulatorTime().get().ge(this.endTime))
142 {
143 return;
144 }
145 synchronized (this.unplacedTemplates)
146 {
147 this.generatedGTUs++;
148 this.unplacedTemplates.add(this.laneBasedGTUCharacteristicsGenerator.draw());
149 if (this.unplacedTemplates.size() == 1)
150 {
151 simulator.scheduleEventNow(this, this, "tryToPlaceGTU", new Object[] {});
152 }
153 }
154 if (this.generatedGTUs < this.maxGTUs)
155 {
156 simulator.scheduleEventRel(this.interarrivelTimeGenerator.draw(), this, this, "generateCharacteristics",
157 new Object[] {});
158 }
159 }
160
161
162 private int lastReportedQueueLength = 0;
163
164
165
166
167
168
169
170
171
172
173 @SuppressWarnings("unused")
174 private void tryToPlaceGTU() throws SimRuntimeException, GTUException, NamingException, NetworkException,
175 OTSGeometryException, ProbabilityException
176 {
177
178 LaneBasedGTUCharacteristics characteristics;
179 OTSDEVSSimulatorInterface simulator = this.laneBasedGTUCharacteristicsGenerator.getSimulator();
180 synchronized (this.unplacedTemplates)
181 {
182 characteristics = this.unplacedTemplates.peek();
183 }
184 if (null == characteristics)
185 {
186 return;
187 }
188 Length shortestHeadway = new Length(Double.MAX_VALUE, LengthUnit.SI);
189 Speed leaderSpeed = null;
190
191 GTUType gtuType = characteristics.getGTUType();
192 for (DirectedLanePosition dlp : this.initialLongitudinalPositions)
193 {
194 Lane lane = dlp.getLane();
195
196 LaneBasedGTU leader = lane.getGtuAhead(dlp.getPosition(), dlp.getGtuDirection(), RelativePosition.FRONT,
197 simulator.getSimulatorTime().getTime());
198
199 Length headway = Length.ZERO;
200 GTUDirectionality leaderDir = dlp.getGtuDirection();
201
202 while (leader == null && (leaderDir.isPlus() && lane.nextLanes(gtuType).size() == 1)
203 || (leaderDir.isMinus() && lane.prevLanes(gtuType).size() == 1) && headway.si < 300)
204 {
205 headway = headway.plus(lane.getLength());
206 if (leaderDir.isPlus())
207 {
208 leaderDir = lane.nextLanes(gtuType).values().iterator().next();
209 lane = lane.nextLanes(gtuType).keySet().iterator().next();
210 }
211 else
212 {
213 leaderDir = lane.prevLanes(gtuType).values().iterator().next();
214 lane = lane.prevLanes(gtuType).keySet().iterator().next();
215 }
216 leader = lane.getGtuAhead(Length.ZERO, leaderDir, RelativePosition.FRONT,
217 simulator.getSimulatorTime().getTime());
218 }
219 if (null != leader)
220 {
221 Length egoPos =
222 dlp.getGtuDirection().isPlus() ? dlp.getPosition() : dlp.getLane().getLength().minus(dlp.getPosition());
223 Length leaderPos = leaderDir.isPlus() ? leader.position(lane, leader.getRear())
224 : lane.getLength().minus(leader.position(lane, leader.getRear()));
225 headway = headway.plus(leaderPos.minus(egoPos));
226
227
228
229
230
231
232 headway = new Length(headway.si - characteristics.getLength().si / 2, LengthUnit.SI);
233 if (shortestHeadway.gt(headway))
234 {
235 shortestHeadway = headway;
236 leaderSpeed = leader.getSpeed();
237 }
238 }
239 }
240 if (shortestHeadway.si > 0)
241 {
242 Speed safeSpeed = characteristics.getSpeed();
243 if (null != leaderSpeed)
244 {
245 safeSpeed = this.roomChecker.canPlace(leaderSpeed, shortestHeadway, characteristics);
246 }
247 if (null != safeSpeed)
248 {
249
250 synchronized (this.unplacedTemplates)
251 {
252 this.unplacedTemplates.remove();
253 }
254 if (safeSpeed.gt(characteristics.getMaximumSpeed()))
255 {
256 safeSpeed = characteristics.getMaximumSpeed();
257 }
258 String gtuId = null == characteristics.getIdGenerator() ? null : characteristics.getIdGenerator().nextId();
259 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU(gtuId, characteristics.getGTUType(),
260 characteristics.getLength(), characteristics.getWidth(), characteristics.getMaximumSpeed(), simulator,
261 characteristics.getNetwork());
262 gtu.setMaximumAcceleration(new Acceleration(3.0, AccelerationUnit.METER_PER_SECOND_2));
263 gtu.setMaximumDeceleration(new Acceleration(-8.0, AccelerationUnit.METER_PER_SECOND_2));
264 gtu.initWithAnimation(characteristics.getStrategicalPlannerFactory().create(gtu, characteristics.getRoute()),
265 this.initialLongitudinalPositions, safeSpeed, DefaultCarAnimation.class, this.gtuColorer);
266
267
268 }
269 }
270 int queueLength = this.unplacedTemplates.size();
271 if (queueLength != this.lastReportedQueueLength)
272 {
273
274
275 this.lastReportedQueueLength = queueLength;
276 }
277 if (queueLength > 0)
278 {
279
280 this.laneBasedGTUCharacteristicsGenerator.getSimulator().scheduleEventRel(this.reTryInterval, this, this,
281 "tryToPlaceGTU", new Object[] {});
282 }
283 }
284
285
286 public String toString()
287 {
288 return "LaneBasedGTUGenerator " + this.id + " on " + this.initialLongitudinalPositions;
289 }
290
291
292
293
294 public long getGeneratedGTUs()
295 {
296 return this.generatedGTUs;
297 }
298
299
300
301
302 public void setGeneratedGTUs(long generatedGTUs)
303 {
304 this.generatedGTUs = generatedGTUs;
305 }
306
307
308
309
310
311 public String getId()
312 {
313 return this.id;
314 }
315
316
317
318
319
320 public Time getEndTime()
321 {
322 return this.endTime;
323 }
324
325
326
327
328
329 public long getMaxGTUs()
330 {
331 return this.maxGTUs;
332 }
333
334
335
336
337
338 public GTUColorer getGtuColorer()
339 {
340 return this.gtuColorer;
341 }
342
343
344
345
346
347 public interface RoomChecker
348 {
349
350
351
352
353
354
355
356
357
358
359
360 public Speed canPlace(final Speed leaderSpeed, final Length headway,
361 final LaneBasedGTUCharacteristics laneBasedGTUCharacteristics) throws NetworkException;
362 }
363
364 }