1 package org.opentrafficsim.demo.strategies;
2
3 import java.awt.Color;
4 import java.awt.Component;
5 import java.awt.Dimension;
6 import java.util.ArrayList;
7 import java.util.Hashtable;
8 import java.util.Iterator;
9 import java.util.List;
10 import java.util.Map;
11
12 import javax.naming.NamingException;
13 import javax.swing.Box;
14 import javax.swing.BoxLayout;
15 import javax.swing.JLabel;
16 import javax.swing.JSlider;
17 import javax.swing.SwingConstants;
18 import javax.swing.border.EmptyBorder;
19 import javax.swing.event.ChangeEvent;
20 import javax.swing.event.ChangeListener;
21
22 import org.djunits.unit.DirectionUnit;
23 import org.djunits.unit.SpeedUnit;
24 import org.djunits.value.vdouble.scalar.Acceleration;
25 import org.djunits.value.vdouble.scalar.Direction;
26 import org.djunits.value.vdouble.scalar.Duration;
27 import org.djunits.value.vdouble.scalar.Length;
28 import org.djunits.value.vdouble.scalar.Speed;
29 import org.djutils.cli.CliException;
30 import org.djutils.cli.CliUtil;
31 import org.djutils.draw.curve.Arc2d;
32 import org.djutils.draw.curve.OffsetCurve2d;
33 import org.djutils.draw.point.DirectedPoint2d;
34 import org.djutils.draw.point.Point2d;
35 import org.djutils.event.Event;
36 import org.djutils.event.EventListener;
37 import org.opentrafficsim.animation.colorer.Colorer;
38 import org.opentrafficsim.animation.colorer.FixedColorer;
39 import org.opentrafficsim.animation.data.gtu.AccelerationGtuColorer;
40 import org.opentrafficsim.animation.data.gtu.DesiredHeadwayGtuColorer;
41 import org.opentrafficsim.animation.data.gtu.IncentiveGtuColorer;
42 import org.opentrafficsim.animation.data.gtu.SocialPressureGtuColorer;
43 import org.opentrafficsim.animation.data.gtu.SpeedGtuColorer;
44 import org.opentrafficsim.base.OtsRuntimeException;
45 import org.opentrafficsim.base.logger.Logger;
46 import org.opentrafficsim.base.parameters.ParameterException;
47 import org.opentrafficsim.base.parameters.ParameterTypes;
48 import org.opentrafficsim.core.definitions.Defaults;
49 import org.opentrafficsim.core.definitions.DefaultsNl;
50 import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
51 import org.opentrafficsim.core.gtu.Gtu;
52 import org.opentrafficsim.core.gtu.GtuCharacteristics;
53 import org.opentrafficsim.core.gtu.GtuException;
54 import org.opentrafficsim.core.gtu.GtuType;
55 import org.opentrafficsim.core.network.Link;
56 import org.opentrafficsim.core.network.Network;
57 import org.opentrafficsim.core.network.NetworkException;
58 import org.opentrafficsim.core.network.Node;
59 import org.opentrafficsim.road.definitions.DefaultsRoadNl;
60 import org.opentrafficsim.road.gtu.LaneBasedGtu;
61 import org.opentrafficsim.road.gtu.LaneBookkeeping;
62 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
63 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
64 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalRoutePlanner;
65 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalRoutePlannerFactory;
66 import org.opentrafficsim.road.gtu.tactical.lmrs.IncentiveSocioSpeed;
67 import org.opentrafficsim.road.gtu.tactical.lmrs.Lmrs;
68 import org.opentrafficsim.road.gtu.tactical.lmrs.LmrsFactory;
69 import org.opentrafficsim.road.gtu.tactical.lmrs.LmrsFactory.Setting;
70 import org.opentrafficsim.road.gtu.tactical.util.lmrs.LmrsParameters;
71 import org.opentrafficsim.road.network.CrossSectionLink;
72 import org.opentrafficsim.road.network.Lane;
73 import org.opentrafficsim.road.network.LaneKeepingPolicy;
74 import org.opentrafficsim.road.network.LanePosition;
75 import org.opentrafficsim.road.network.RoadNetwork;
76 import org.opentrafficsim.road.network.factory.LaneFactory;
77 import org.opentrafficsim.road.network.speed.LaneSpeedLimits;
78 import org.opentrafficsim.swing.gui.OtsSimulationPanel;
79 import org.opentrafficsim.swing.gui.OtsSimulationPanel.DemoPanelPosition;
80 import org.opentrafficsim.swing.gui.OtsSimulationPanelDecorator;
81 import org.opentrafficsim.swing.script.AbstractSimulationScript;
82
83 import nl.tudelft.simulation.dsol.SimRuntimeException;
84 import nl.tudelft.simulation.jstats.distributions.DistNormal;
85 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
86 import nl.tudelft.simulation.jstats.streams.StreamInterface;
87 import picocli.CommandLine.Option;
88
89
90
91
92
93
94
95
96
97 public class StrategiesDemo extends AbstractSimulationScript
98 {
99
100 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalRoutePlanner> factory;
101
102
103 private int gtuIdNum = 0;
104
105
106 private int gtuNum = 60;
107
108
109 private final StreamInterface stream = new MersenneTwister(1L);
110
111
112 private final List<Double> queue = new ArrayList<>();
113
114
115 private KmplcListener kmplcListener;
116
117
118 private double truckFraction = 0.1;
119
120
121 private GtuType nextGtuType;
122
123
124 private Length truckLength;
125
126
127 private Length truckMid;
128
129
130 @Option(names = "--length", description = "Length", defaultValue = "2m")
131 private Length carLength;
132
133
134 private Length carMid;
135
136
137
138
139 protected StrategiesDemo()
140 {
141 super("Strategies demo", "Demo of driving strategies in LMRS.");
142 try
143 {
144 CliUtil.changeOptionDefault(this, "simulationTime", "3600000s");
145 }
146 catch (NoSuchFieldException | IllegalStateException | IllegalArgumentException | CliException exception)
147 {
148 throw new OtsRuntimeException(exception);
149 }
150 }
151
152 @Override
153 protected OtsSimulationPanelDecorator getDecorator()
154 {
155 return new OtsSimulationPanelDecorator()
156 {
157 @Override
158 public void setupDemo(final OtsSimulationPanel simulationPanel, final Network network)
159 {
160 StrategiesDemo.this.setupDemo(simulationPanel, network);
161 }
162
163 @Override
164 public List<Colorer<? super Gtu>> getGtuColorers()
165 {
166 return List.of(new FixedColorer<>(Color.BLUE, "Blue"), new SpeedGtuColorer(), new AccelerationGtuColorer(),
167 new SocialPressureGtuColorer(), new DesiredHeadwayGtuColorer(Duration.ofSI(0.5), Duration.ofSI(1.6)),
168 new IncentiveGtuColorer(IncentiveSocioSpeed.class));
169 }
170 };
171 }
172
173
174
175
176
177 public static void main(final String[] args)
178 {
179 StrategiesDemo demo = new StrategiesDemo();
180 CliUtil.execute(demo, args);
181 try
182 {
183 demo.start();
184 }
185 catch (Exception ex)
186 {
187 ex.printStackTrace();
188 }
189 }
190
191
192
193
194
195
196 private void setupDemo(final OtsSimulationPanel simulationPanel, final Network network)
197 {
198
199 simulationPanel.createDemoPanel(DemoPanelPosition.RIGHT);
200 simulationPanel.getDemoPanel().setBorder(new EmptyBorder(10, 10, 10, 10));
201 simulationPanel.getDemoPanel().setLayout(new BoxLayout(simulationPanel.getDemoPanel(), BoxLayout.Y_AXIS));
202 simulationPanel.getDemoPanel().setPreferredSize(new Dimension(300, 300));
203
204
205 JLabel textLabel = new JLabel("<html><p align=\"justify\">"
206 + "Adjust the sliders below to change the ego-speed sensitivity and socio-speed sensitivity of the drivers, "
207 + "and observe how traffic is affected." + "</html>");
208 textLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
209 simulationPanel.getDemoPanel().add(textLabel);
210
211
212 simulationPanel.getDemoPanel().add(Box.createVerticalStrut(20));
213
214
215 JLabel gtuLabel = new JLabel("<html>Number of vehicles</html>");
216 gtuLabel.setHorizontalAlignment(SwingConstants.CENTER);
217 gtuLabel.setPreferredSize(new Dimension(200, 0));
218 gtuLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
219 simulationPanel.getDemoPanel().add(gtuLabel);
220 JSlider gtuSlider = new JSlider(0, 120, this.gtuNum);
221 gtuSlider.setMinorTickSpacing(10);
222 gtuSlider.setMajorTickSpacing(30);
223 gtuSlider.setPaintTicks(true);
224 gtuSlider.setPaintLabels(true);
225 gtuSlider.setToolTipText("<html>Number of vehicles</html>");
226 gtuSlider.addChangeListener(new ChangeListener()
227 {
228 @SuppressWarnings("synthetic-access")
229 @Override
230 public void stateChanged(final ChangeEvent e)
231 {
232 StrategiesDemo.this.gtuNum = ((JSlider) e.getSource()).getValue();
233 if (!StrategiesDemo.this.getSimulator().isStartingOrRunning())
234 {
235
236 simulationPanel.getDemoPanel().getParent().repaint();
237 }
238 }
239 });
240 simulationPanel.getDemoPanel().add(gtuSlider);
241
242
243 simulationPanel.getDemoPanel().add(Box.createVerticalStrut(20));
244
245
246 JLabel egoLabel = new JLabel("<html>Ego-speed sensitivity<sup>-1</sup> [km/h]</html>");
247 egoLabel.setHorizontalAlignment(SwingConstants.CENTER);
248 egoLabel.setPreferredSize(new Dimension(200, 0));
249 egoLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
250 simulationPanel.getDemoPanel().add(egoLabel);
251 int egoSteps = 70;
252 JSlider egoSlider = new JSlider(0, egoSteps, egoSteps / 2);
253 egoSlider.setMinorTickSpacing(2);
254 egoSlider.setMajorTickSpacing(egoSteps / 5);
255 egoSlider.setPaintTicks(true);
256 egoSlider.setPaintLabels(true);
257 Hashtable<Integer, JLabel> egoTable = new Hashtable<>();
258 for (int i = 0; i <= egoSteps; i += egoSteps / 5)
259 {
260 egoTable.put(i, new JLabel(String.format("%d", i)));
261 }
262 egoSlider.setLabelTable(egoTable);
263 egoSlider.setToolTipText("<html>Ego-speed sensitivity as 1/<i>v<sub>gain</sub></i></html>");
264 egoSlider.addChangeListener(new ChangeListener()
265 {
266
267 private boolean loggedException = false;
268
269 @Override
270 public void stateChanged(final ChangeEvent e)
271 {
272 double v = Math.max(((JSlider) e.getSource()).getValue(), 0.01);
273 Speed vGain = new Speed(v, SpeedUnit.KM_PER_HOUR);
274 for (Gtu gtu : getNetwork().getGTUs())
275 {
276 if (gtu.getType().isOfType(DefaultsNl.CAR))
277 {
278 try
279 {
280 gtu.getParameters().setClaimedParameter(LmrsParameters.VGAIN, vGain, egoSlider);
281 }
282 catch (ParameterException exception)
283 {
284 if (!this.loggedException)
285 {
286 Logger.ots().error("Unable to set VGAIN on GTU.");
287 this.loggedException = true;
288 }
289 }
290 }
291 }
292 }
293 });
294 simulationPanel.getDemoPanel().add(egoSlider);
295
296
297 simulationPanel.getDemoPanel().add(Box.createVerticalStrut(20));
298
299
300 JLabel socioLabel = new JLabel("Socio-speed sensitivity [-]");
301 socioLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
302 simulationPanel.getDemoPanel().add(socioLabel);
303 int socioSteps = 20;
304 JSlider socioSlider = new JSlider(0, socioSteps, socioSteps / 2);
305 socioSlider.setMinorTickSpacing(1);
306 socioSlider.setMajorTickSpacing(socioSteps / 5);
307 socioSlider.setPaintTicks(true);
308 socioSlider.setPaintLabels(true);
309 Hashtable<Integer, JLabel> socioTable = new Hashtable<>();
310 for (int i = 0; i <= socioSteps; i += socioSteps / 5)
311 {
312 double val = (double) i / socioSteps;
313 socioTable.put(i, new JLabel(String.format("%.2f", val)));
314 }
315 socioSlider.setLabelTable(socioTable);
316 socioSlider.setToolTipText("Socio-speed sensitivity between 0 and 1");
317 socioSlider.addChangeListener(new ChangeListener()
318 {
319
320 private boolean loggedException = false;
321
322 @Override
323 public void stateChanged(final ChangeEvent e)
324 {
325 JSlider slider = (JSlider) e.getSource();
326 double sigma = ((double) slider.getValue()) / slider.getMaximum();
327 for (Gtu gtu : getNetwork().getGTUs())
328 {
329 if (gtu.getType().isOfType(DefaultsNl.CAR))
330 {
331 try
332 {
333 gtu.getParameters().setClaimedParameter(LmrsParameters.SOCIO, sigma, socioSlider);
334 }
335 catch (ParameterException exception)
336 {
337 if (!this.loggedException)
338 {
339 Logger.ots().error("Unable to set SOCIO on GTU.");
340 }
341 this.loggedException = true;
342 }
343 }
344 }
345 }
346 });
347 simulationPanel.getDemoPanel().add(socioSlider);
348
349
350 simulationPanel.getDemoPanel().add(Box.createVerticalStrut(20));
351
352
353 JLabel kmplcLabel = new JLabel("Km between lane changes (last 0): -");
354 this.kmplcListener = new KmplcListener(kmplcLabel, (RoadNetwork) network);
355 for (Gtu gtu : network.getGTUs())
356 {
357 gtu.addListener(this.kmplcListener, LaneBasedGtu.LANE_CHANGE_EVENT);
358 }
359 kmplcLabel.setHorizontalAlignment(SwingConstants.LEFT);
360 kmplcLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
361 simulationPanel.getDemoPanel().add(kmplcLabel);
362 }
363
364
365
366
367 @SuppressWarnings("unused")
368 private void checkVehicleNumber()
369 {
370 while (getNetwork().getGTUs().size() > this.gtuNum)
371 {
372 int n = getNetwork().getGTUs().size();
373 int i = n <= 1 ? 0 : StrategiesDemo.this.stream.nextInt(0, n - 1);
374 Iterator<Gtu> it = getNetwork().getGTUs().iterator();
375 Gtu gtu = it.next();
376 for (int j = 0; j < i; j++)
377 {
378 gtu = it.next();
379 }
380 gtu.destroy();
381 this.queue.clear();
382 }
383
384 if (getNetwork().getGTUs().size() < this.gtuNum)
385 {
386 Lane lane = null;
387 Length pos = null;
388 Speed initialSpeed = null;
389 Length gap = Length.ZERO;
390 for (Link link : getNetwork().getLinkMap().values())
391 {
392 for (Lane l : ((CrossSectionLink) link).getLanes())
393 {
394 if (l.numberOfGtus() == 0)
395 {
396 lane = l;
397 pos = lane.getLength().times(0.5);
398 gap = Length.POSITIVE_INFINITY;
399 initialSpeed = Speed.ZERO;
400 }
401 for (int i = 0; i < l.numberOfGtus(); i++)
402 {
403 LaneBasedGtu gtu1 = l.getGtu(i);
404 Length up = gtu1.getPosition(l, gtu1.getFront());
405 LaneBasedGtu gtu2;
406 Length down;
407 if (i < l.numberOfGtus() - 1)
408 {
409 gtu2 = l.getGtu(i + 1);
410 down = gtu2.getPosition(l, gtu2.getRear());
411 }
412 else
413 {
414 Lane nextLane = l.nextLanes(DefaultsNl.VEHICLE).iterator().next();
415 if (nextLane.numberOfGtus() == 0)
416 {
417 continue;
418 }
419 gtu2 = nextLane.getGtu(0);
420 down = l.getLength().plus(gtu2.getPosition(nextLane, gtu2.getRear()));
421 }
422 Length tentativeGap = down.minus(up)
423 .minus(this.nextGtuType.isOfType(DefaultsNl.TRUCK) ? this.truckLength : this.carLength);
424 if (tentativeGap.gt(gap))
425 {
426
427 Speed maxSpeed = Speed.max(gtu1.getSpeed(), gtu2.getSpeed());
428 if (maxSpeed.eq0() || tentativeGap.divide(maxSpeed).si * .5 > .3)
429 {
430 gap = tentativeGap;
431 initialSpeed = Speed.interpolate(gtu1.getSpeed(), gtu2.getSpeed(), 0.5);
432 pos = up.plus(tentativeGap.times(0.5))
433 .minus(this.nextGtuType.isOfType(DefaultsNl.TRUCK) ? this.truckMid : this.carMid);
434 if (pos.gt(l.getLength()))
435 {
436 pos = pos.minus(l.getLength());
437 lane = l.nextLanes(DefaultsNl.VEHICLE).iterator().next();
438 }
439 else
440 {
441 lane = l;
442 }
443 }
444 }
445 }
446 }
447 }
448 if (lane != null)
449 {
450 try
451 {
452 createGtu(lane, pos, this.nextGtuType, initialSpeed, getNetwork());
453 }
454 catch (NamingException | GtuException | NetworkException | SimRuntimeException exception)
455 {
456 throw new OtsRuntimeException(exception);
457 }
458 this.nextGtuType = this.stream.nextDouble() < this.truckFraction ? DefaultsNl.TRUCK : DefaultsNl.CAR;
459 this.queue.clear();
460 }
461 }
462 getSimulator().scheduleEventRel(Duration.ofSI(0.5), () -> checkVehicleNumber());
463 }
464
465
466 private class KmplcListener implements EventListener
467 {
468
469 private final JLabel label;
470
471
472 private final RoadNetwork network;
473
474
475
476
477
478
479 @SuppressWarnings("synthetic-access")
480 KmplcListener(final JLabel label, final RoadNetwork network)
481 {
482 this.label = label;
483 this.network = network;
484 StrategiesDemo.this.queue.add(0.0);
485 }
486
487 @SuppressWarnings("synthetic-access")
488 @Override
489 public void notify(final Event event)
490 {
491 if (event.getType().equals(LaneBasedGtu.LANE_CHANGE_EVENT))
492 {
493 double cumul = 0.0;
494 for (Gtu gtu : this.network.getGTUs())
495 {
496 cumul += gtu.getOdometer().si;
497 }
498 cumul /= 1000;
499 StrategiesDemo.this.queue.add(cumul);
500 while (StrategiesDemo.this.queue.size() > 51)
501 {
502 StrategiesDemo.this.queue.remove(0);
503 }
504 double val =
505 (StrategiesDemo.this.queue.get(StrategiesDemo.this.queue.size() - 1) - StrategiesDemo.this.queue.get(0))
506 / (StrategiesDemo.this.queue.size() - 1.0);
507 this.label.setText(
508 String.format("Lane change rate (last %d): %.1f km/lc", StrategiesDemo.this.queue.size() - 1, val));
509 }
510 }
511 }
512
513 @Override
514 protected RoadNetwork setupSimulation(final OtsSimulatorInterface sim) throws Exception
515 {
516 RoadNetwork network = new RoadNetwork("Strategies demo", getSimulator());
517
518 GtuCharacteristics truck = Defaults.NL.apply(DefaultsNl.TRUCK, this.stream)
519 .orElseThrow(() -> new GtuException("No characteristics for NL.TRUCK could be generated.")).get();
520 GtuCharacteristics car = Defaults.NL.apply(DefaultsNl.CAR, this.stream)
521 .orElseThrow(() -> new GtuException("No characteristics for NL.CAR could be generated.")).get();
522 this.truckLength = truck.getLength();
523 this.truckMid = truck.getLength().times(0.5).minus(truck.getFront());
524 this.carLength = car.getLength();
525 this.carMid = car.getLength().times(0.5).minus(car.getFront());
526
527 double radius = 150;
528 LaneSpeedLimits speedLimits = new LaneSpeedLimits(new Speed(120, SpeedUnit.KM_PER_HOUR),
529 Map.of(DefaultsNl.TRUCK, new Speed(80, SpeedUnit.KM_PER_HOUR)));
530 Node nodeA = new Node(network, "A", new Point2d(-radius, 0), new Direction(270, DirectionUnit.EAST_DEGREE));
531 Node nodeB = new Node(network, "B", new Point2d(radius, 0), new Direction(90, DirectionUnit.EAST_DEGREE));
532
533 OffsetCurve2d half1 = new Arc2d(new DirectedPoint2d(radius, 0.0, Math.PI / 2), radius, true, Math.PI);
534 List<Lane> lanes1 = new LaneFactory(network, nodeB, nodeA, DefaultsNl.FREEWAY, sim, LaneKeepingPolicy.KEEPRIGHT, half1)
535 .leftToRight(0.0, Length.ofSI(3.5), DefaultsRoadNl.FREEWAY, speedLimits).addLanes(DefaultsRoadNl.DASHED)
536 .getLanes();
537 OffsetCurve2d half2 = new Arc2d(new DirectedPoint2d(-radius, 0.0, -Math.PI / 2), radius, true, Math.PI);
538 List<Lane> lanes2 = new LaneFactory(network, nodeA, nodeB, DefaultsNl.FREEWAY, sim, LaneKeepingPolicy.KEEPRIGHT, half2)
539 .leftToRight(0.0, Length.ofSI(3.5), DefaultsRoadNl.FREEWAY, speedLimits).addLanes(DefaultsRoadNl.DASHED)
540 .getLanes();
541
542 LmrsFactory<Lmrs> lmrsFactory = new LmrsFactory<>(Lmrs::new).set(Setting.SOCIO_TAILGATING, true)
543 .set(Setting.SOCIO_LANE_CHANGE, true).set(Setting.SOCIO_SPEED, true)
544 .set(Setting.INCENTIVE_STAY_ON_SLOW_LANES, true, DefaultsNl.TRUCK).setStream(this.stream);
545 lmrsFactory.addParameter(DefaultsNl.CAR, LmrsParameters.SOCIO, 0.5);
546 lmrsFactory.addParameter(DefaultsNl.TRUCK, LmrsParameters.SOCIO, 1.0);
547 lmrsFactory.addParameter(DefaultsNl.CAR, LmrsParameters.VGAIN, new Speed(35.0, SpeedUnit.KM_PER_HOUR));
548 lmrsFactory.addParameter(DefaultsNl.TRUCK, LmrsParameters.VGAIN, new Speed(50.0, SpeedUnit.KM_PER_HOUR));
549 lmrsFactory.addParameter(ParameterTypes.TMAX, Duration.ofSI(1.6));
550 lmrsFactory.addParameter(DefaultsNl.TRUCK, ParameterTypes.A, Acceleration.ofSI(0.4));
551 lmrsFactory.addParameter(DefaultsNl.TRUCK, ParameterTypes.FSPEED, 1.0);
552 lmrsFactory.addParameter(DefaultsNl.TRUCK, ParameterTypes.FSPEED_GTU,
553 new DistNormal(this.stream, 85.0 / 80.0, 2.5 / 80.0));
554 this.factory = new LaneBasedStrategicalRoutePlannerFactory(lmrsFactory, lmrsFactory);
555
556 for (int i = 0; i < lanes1.size(); i++)
557 {
558 Length pos = Length.ofSI(10.0);
559 Length gap = lanes1.get(i).getLength().plus(lanes2.get(i).getLength()).divide(this.gtuNum / 2);
560 for (int j = 0; j < 2; j++)
561 {
562 Lane lane = j == 0 ? lanes1.get(i) : lanes2.get(i);
563 while (true)
564 {
565 GtuType gtuType;
566 if (i == 0)
567 {
568 gtuType = DefaultsNl.CAR;
569 }
570 else
571 {
572 gtuType = this.stream.nextDouble() < 2 * this.truckFraction ? DefaultsNl.TRUCK : DefaultsNl.CAR;
573 }
574
575 Speed initialSpeed = Speed.ZERO;
576
577 createGtu(lane, pos, gtuType, initialSpeed, network);
578
579 pos = pos.plus(gap);
580 if (pos.si > lane.getLength().si)
581 {
582 pos = pos.minus(lane.getLength());
583 break;
584 }
585 }
586 }
587 }
588
589 this.nextGtuType = this.stream.nextDouble() < this.truckFraction ? DefaultsNl.TRUCK : DefaultsNl.CAR;
590 sim.scheduleEventNow(() -> checkVehicleNumber());
591
592 return network;
593 }
594
595
596
597
598
599
600
601
602
603
604
605
606
607 public void createGtu(final Lane lane, final Length pos, final GtuType gtuType, final Speed initialSpeed,
608 final RoadNetwork net) throws NamingException, GtuException, NetworkException, SimRuntimeException
609 {
610 GtuCharacteristics gtuCharacteristics = Defaults.NL.apply(gtuType, this.stream)
611 .orElseThrow(() -> new GtuException("No characteristics for GTU type " + gtuType + " could be generated."))
612 .get();
613
614 LaneBasedGtu gtu = new LaneBasedGtu("" + (++this.gtuIdNum), gtuType, gtuCharacteristics.getLength(),
615 gtuCharacteristics.getWidth(), gtuCharacteristics.getMaximumSpeed(), gtuCharacteristics.getFront(), net);
616 gtu.setMaximumAcceleration(gtuCharacteristics.getMaximumAcceleration());
617 gtu.setMaximumDeceleration(gtuCharacteristics.getMaximumDeceleration());
618 gtu.setNoLaneChangeDistance(Length.ofSI(50));
619 gtu.setBookkeeping(LaneBookkeeping.INSTANT);
620
621
622 LaneBasedStrategicalPlanner strategicalPlanner = this.factory.create(gtu, null, null, null);
623
624
625
626 gtu.init(strategicalPlanner, new LanePosition(lane, pos).getLocation(), initialSpeed);
627
628 if (this.kmplcListener != null)
629 {
630 gtu.addListener(this.kmplcListener, LaneBasedGtu.LANE_CHANGE_EVENT);
631 }
632 }
633
634 }