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