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