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.Hashtable;
9 import java.util.Iterator;
10 import java.util.LinkedHashMap;
11 import java.util.LinkedHashSet;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Set;
15
16 import javax.naming.NamingException;
17 import javax.swing.Box;
18 import javax.swing.BoxLayout;
19 import javax.swing.JLabel;
20 import javax.swing.JSlider;
21 import javax.swing.SwingConstants;
22 import javax.swing.border.EmptyBorder;
23 import javax.swing.event.ChangeEvent;
24 import javax.swing.event.ChangeListener;
25
26 import org.djunits.unit.DirectionUnit;
27 import org.djunits.unit.SpeedUnit;
28 import org.djunits.value.vdouble.scalar.Acceleration;
29 import org.djunits.value.vdouble.scalar.Direction;
30 import org.djunits.value.vdouble.scalar.Duration;
31 import org.djunits.value.vdouble.scalar.Length;
32 import org.djunits.value.vdouble.scalar.Speed;
33 import org.djutils.cli.CliException;
34 import org.djutils.cli.CliUtil;
35 import org.djutils.event.Event;
36 import org.djutils.event.EventListener;
37 import org.djutils.exceptions.Try;
38 import org.opentrafficsim.base.parameters.ParameterException;
39 import org.opentrafficsim.base.parameters.ParameterSet;
40 import org.opentrafficsim.base.parameters.ParameterTypes;
41 import org.opentrafficsim.base.parameters.Parameters;
42 import org.opentrafficsim.core.animation.gtu.colorer.AccelerationGtuColorer;
43 import org.opentrafficsim.core.animation.gtu.colorer.SpeedGtuColorer;
44 import org.opentrafficsim.core.animation.gtu.colorer.SwitchableGtuColorer;
45 import org.opentrafficsim.core.definitions.Defaults;
46 import org.opentrafficsim.core.definitions.DefaultsNl;
47 import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
48 import org.opentrafficsim.core.geometry.OtsGeometryException;
49 import org.opentrafficsim.core.geometry.OtsLine3d;
50 import org.opentrafficsim.core.geometry.OtsPoint3d;
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.gtu.perception.DirectEgoPerception;
56 import org.opentrafficsim.core.network.Link;
57 import org.opentrafficsim.core.network.NetworkException;
58 import org.opentrafficsim.core.network.Node;
59 import org.opentrafficsim.core.parameters.ParameterFactoryByType;
60 import org.opentrafficsim.road.definitions.DefaultsRoadNl;
61 import org.opentrafficsim.road.gtu.colorer.DesiredHeadwayColorer;
62 import org.opentrafficsim.road.gtu.colorer.FixedColor;
63 import org.opentrafficsim.road.gtu.colorer.IncentiveColorer;
64 import org.opentrafficsim.road.gtu.colorer.SocialPressureColorer;
65 import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
66 import org.opentrafficsim.road.gtu.lane.perception.CategoricalLanePerception;
67 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
68 import org.opentrafficsim.road.gtu.lane.perception.PerceptionFactory;
69 import org.opentrafficsim.road.gtu.lane.perception.categories.AnticipationTrafficPerception;
70 import org.opentrafficsim.road.gtu.lane.perception.categories.DirectInfrastructurePerception;
71 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.DirectNeighborsPerception;
72 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.HeadwayGtuType;
73 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIdm;
74 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
75 import org.opentrafficsim.road.gtu.lane.tactical.following.IdmPlus;
76 import org.opentrafficsim.road.gtu.lane.tactical.following.IdmPlusFactory;
77 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationIncentive;
78 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
79 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
80 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSocioSpeed;
81 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
82 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveStayRight;
83 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LmrsFactory;
84 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.SocioDesiredSpeed;
85 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
86 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
87 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
88 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
89 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
90 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
91 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
92 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
93 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
94 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalRoutePlannerFactory;
95 import org.opentrafficsim.road.network.RoadNetwork;
96 import org.opentrafficsim.road.network.factory.LaneFactory;
97 import org.opentrafficsim.road.network.lane.CrossSectionLink;
98 import org.opentrafficsim.road.network.lane.Lane;
99 import org.opentrafficsim.road.network.lane.LanePosition;
100 import org.opentrafficsim.road.network.lane.Stripe.Type;
101 import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
102 import org.opentrafficsim.swing.gui.OtsAnimationPanel;
103 import org.opentrafficsim.swing.gui.OtsAnimationPanel.DemoPanelPosition;
104 import org.opentrafficsim.swing.script.AbstractSimulationScript;
105
106 import nl.tudelft.simulation.dsol.SimRuntimeException;
107 import nl.tudelft.simulation.jstats.distributions.DistNormal;
108 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
109 import nl.tudelft.simulation.jstats.streams.StreamInterface;
110 import picocli.CommandLine.Option;
111
112
113
114
115
116
117
118
119
120 public class StrategiesDemo extends AbstractSimulationScript
121 {
122
123 private final Map<GtuType, LaneBasedStrategicalPlannerFactory<?>> factories = new LinkedHashMap<>();
124
125
126 private int gtuIdNum = 0;
127
128
129 private int gtuNum = 60;
130
131
132 private final StreamInterface stream = new MersenneTwister(1L);
133
134
135 private final List<Double> queue = new ArrayList<>();
136
137
138 private KmplcListener kmplcListener;
139
140
141 private double truckFraction = 0.1;
142
143
144 private GtuType nextGtuType;
145
146
147 private Length truckLength;
148
149
150 private Length truckMid;
151
152
153 @Option(names = "--length", description = "Length", defaultValue = "2m")
154 private Length carLength;
155
156
157 private Length carMid;
158
159
160
161
162 protected StrategiesDemo()
163 {
164 super("Strategies demo", "Demo of driving strategies in LMRS.");
165 setGtuColorer(SwitchableGtuColorer.builder().addColorer(new FixedColor(Color.BLUE, "Blue"))
166 .addColorer(new SpeedGtuColorer(new Speed(150, SpeedUnit.KM_PER_HOUR)))
167 .addColorer(new AccelerationGtuColorer(Acceleration.instantiateSI(-6.0), Acceleration.instantiateSI(2)))
168 .addActiveColorer(new SocialPressureColorer())
169 .addColorer(new DesiredHeadwayColorer(Duration.instantiateSI(0.5), Duration.instantiateSI(1.6)))
170 .addColorer(new IncentiveColorer(IncentiveSocioSpeed.class)).build());
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
200 @Override
201 protected void setupDemo(final OtsAnimationPanel animation, final RoadNetwork network)
202 {
203
204 animation.createDemoPanel(DemoPanelPosition.RIGHT);
205 animation.getDemoPanel().setBorder(new EmptyBorder(10, 10, 10, 10));
206 animation.getDemoPanel().setLayout(new BoxLayout(animation.getDemoPanel(), BoxLayout.Y_AXIS));
207 animation.getDemoPanel().setPreferredSize(new Dimension(300, 300));
208
209
210 JLabel textLabel = new JLabel("<html><p align=\"justify\">"
211 + "Adjust the sliders below to change the ego-speed sensitivity and socio-speed sensitivity of the drivers, "
212 + "and observe how traffic is affected. Detailed instructions are in the attached read-me." + "</html>");
213 textLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
214 animation.getDemoPanel().add(textLabel);
215
216
217 animation.getDemoPanel().add(Box.createVerticalStrut(20));
218
219
220 JLabel gtuLabel = new JLabel("<html>Number of vehicles</html>");
221 gtuLabel.setHorizontalAlignment(SwingConstants.CENTER);
222 gtuLabel.setPreferredSize(new Dimension(200, 0));
223 gtuLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
224 animation.getDemoPanel().add(gtuLabel);
225 JSlider gtuSlider = new JSlider(0, 120, this.gtuNum);
226 gtuSlider.setMinorTickSpacing(10);
227 gtuSlider.setMajorTickSpacing(30);
228 gtuSlider.setPaintTicks(true);
229 gtuSlider.setPaintLabels(true);
230 gtuSlider.setToolTipText("<html>Number of vehicles</html>");
231 gtuSlider.addChangeListener(new ChangeListener()
232 {
233 @SuppressWarnings("synthetic-access")
234 @Override
235 public void stateChanged(final ChangeEvent e)
236 {
237 StrategiesDemo.this.gtuNum = ((JSlider) e.getSource()).getValue();
238 if (!StrategiesDemo.this.getSimulator().isStartingOrRunning())
239 {
240
241 animation.getDemoPanel().getParent().repaint();
242 }
243 }
244 });
245 animation.getDemoPanel().add(gtuSlider);
246
247
248 animation.getDemoPanel().add(Box.createVerticalStrut(20));
249
250
251 JLabel egoLabel = new JLabel("<html>Ego-speed sensitivity<sup>-1</sup> [km/h]</html>");
252 egoLabel.setHorizontalAlignment(SwingConstants.CENTER);
253 egoLabel.setPreferredSize(new Dimension(200, 0));
254 egoLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
255 animation.getDemoPanel().add(egoLabel);
256 int egoSteps = 70;
257 JSlider egoSlider = new JSlider(0, egoSteps, egoSteps / 2);
258 egoSlider.setMinorTickSpacing(2);
259 egoSlider.setMajorTickSpacing(egoSteps / 5);
260 egoSlider.setPaintTicks(true);
261 egoSlider.setPaintLabels(true);
262 Hashtable<Integer, JLabel> egoTable = new Hashtable<>();
263 for (int i = 0; i <= egoSteps; i += egoSteps / 5)
264 {
265 egoTable.put(i, new JLabel(String.format("%d", i)));
266 }
267 egoSlider.setLabelTable(egoTable);
268 egoSlider.setToolTipText("<html>Ego-speed sensitivity as 1/<i>v<sub>gain</sub></i></html>");
269 egoSlider.addChangeListener(new ChangeListener()
270 {
271 @Override
272 public void stateChanged(final ChangeEvent e)
273 {
274 double v = Math.max(((JSlider) e.getSource()).getValue(), 0.01);
275 Speed vGain = new Speed(v, SpeedUnit.KM_PER_HOUR);
276 for (Gtu gtu : getNetwork().getGTUs())
277 {
278 if (gtu.getType().isOfType(DefaultsNl.CAR))
279 {
280 Try.execute(() -> gtu.getParameters().setParameter(LmrsParameters.VGAIN, vGain),
281 "Exception while setting vGain");
282 }
283 }
284 }
285 });
286 animation.getDemoPanel().add(egoSlider);
287
288
289 animation.getDemoPanel().add(Box.createVerticalStrut(20));
290
291
292 JLabel socioLabel = new JLabel("Socio-speed sensitivity [-]");
293 socioLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
294 animation.getDemoPanel().add(socioLabel);
295 int socioSteps = 20;
296 JSlider socioSlider = new JSlider(0, socioSteps, socioSteps / 2);
297 socioSlider.setMinorTickSpacing(1);
298 socioSlider.setMajorTickSpacing(socioSteps / 5);
299 socioSlider.setPaintTicks(true);
300 socioSlider.setPaintLabels(true);
301 Hashtable<Integer, JLabel> socioTable = new Hashtable<>();
302 for (int i = 0; i <= socioSteps; i += socioSteps / 5)
303 {
304 double val = (double) i / socioSteps;
305 socioTable.put(i, new JLabel(String.format("%.2f", val)));
306 }
307 socioSlider.setLabelTable(socioTable);
308 socioSlider.setToolTipText("Socio-speed sensitivity between 0 and 1");
309 socioSlider.addChangeListener(new ChangeListener()
310 {
311 @Override
312 public void stateChanged(final ChangeEvent e)
313 {
314 JSlider slider = (JSlider) e.getSource();
315 double sigma = ((double) slider.getValue()) / slider.getMaximum();
316 for (Gtu gtu : getNetwork().getGTUs())
317 {
318 if (gtu.getType().isOfType(DefaultsNl.CAR))
319 {
320 Try.execute(() -> gtu.getParameters().setParameter(LmrsParameters.SOCIO, sigma),
321 "Exception while setting vGain");
322 }
323 }
324 }
325 });
326 animation.getDemoPanel().add(socioSlider);
327
328
329 animation.getDemoPanel().add(Box.createVerticalStrut(20));
330
331
332 JLabel kmplcLabel = new JLabel("Km between lane changes (last 0): -");
333 this.kmplcListener = new KmplcListener(kmplcLabel, network);
334 for (Gtu gtu : network.getGTUs())
335 {
336 Try.execute(() -> gtu.addListener(this.kmplcListener, LaneBasedGtu.LANE_CHANGE_EVENT),
337 "Exception while adding lane change listener");
338 }
339 kmplcLabel.setHorizontalAlignment(SwingConstants.LEFT);
340 kmplcLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
341 animation.getDemoPanel().add(kmplcLabel);
342 }
343
344
345
346
347 @SuppressWarnings("unused")
348 private void checkVehicleNumber()
349 {
350 while (getNetwork().getGTUs().size() > this.gtuNum)
351 {
352 int i = StrategiesDemo.this.stream.nextInt(0, getNetwork().getGTUs().size());
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 | OtsGeometryException 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
469 @SuppressWarnings("synthetic-access")
470 @Override
471 public void notify(final Event event) throws RemoteException
472 {
473 if (event.getType().equals(LaneBasedGtu.LANE_CHANGE_EVENT))
474 {
475 double cumul = 0.0;
476 for (Gtu gtu : this.network.getGTUs())
477 {
478 cumul += gtu.getOdometer().si;
479 }
480 cumul /= 1000;
481 StrategiesDemo.this.queue.add(cumul);
482 while (StrategiesDemo.this.queue.size() > 51)
483 {
484 StrategiesDemo.this.queue.remove(0);
485 }
486 double val =
487 (StrategiesDemo.this.queue.get(StrategiesDemo.this.queue.size() - 1) - StrategiesDemo.this.queue.get(0))
488 / (StrategiesDemo.this.queue.size() - 1.0);
489 this.label.setText(
490 String.format("Lane change rate (last %d): %.1f km/lc", StrategiesDemo.this.queue.size() - 1, val));
491 }
492 }
493 }
494
495
496 @Override
497 protected RoadNetwork setupSimulation(final OtsSimulatorInterface sim) throws Exception
498 {
499 RoadNetwork network = new RoadNetwork("Strategies demo", getSimulator());
500
501 GtuType.registerTemplateSupplier(DefaultsNl.TRUCK, Defaults.NL);
502 GtuType.registerTemplateSupplier(DefaultsNl.CAR, Defaults.NL);
503 GtuCharacteristics truck = GtuType.defaultCharacteristics(DefaultsNl.TRUCK, network, this.stream);
504 GtuCharacteristics car = GtuType.defaultCharacteristics(DefaultsNl.CAR, network, this.stream);
505 this.truckLength = truck.getLength();
506 this.truckMid = truck.getLength().times(0.5).minus(truck.getFront());
507 this.carLength = car.getLength();
508 this.carMid = car.getLength().times(0.5).minus(car.getFront());
509
510 double radius = 150;
511 Speed speedLimit = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
512 Node nodeA =
513 new Node(network, "A", new OtsPoint3d(-radius, 0, 0), new Direction(270, DirectionUnit.EAST_DEGREE));
514 Node nodeB =
515 new Node(network, "B", new OtsPoint3d(radius, 0, 0), new Direction(90, DirectionUnit.EAST_DEGREE));
516
517 OtsPoint3d[] coordsHalf1 = new OtsPoint3d[127];
518 for (int i = 0; i < coordsHalf1.length; i++)
519 {
520 double angle = Math.PI * (i) / (coordsHalf1.length - 1);
521 coordsHalf1[i] = new OtsPoint3d(radius * Math.cos(angle), radius * Math.sin(angle), 0);
522 }
523 List<Lane> lanes1 = new LaneFactory(network, nodeB, nodeA, DefaultsNl.FREEWAY, sim, LaneKeepingPolicy.KEEPLEFT,
524 DefaultsNl.VEHICLE, new OtsLine3d(coordsHalf1))
525 .leftToRight(0.0, Length.instantiateSI(3.5), DefaultsRoadNl.FREEWAY, speedLimit).addLanes(Type.DASHED)
526 .getLanes();
527 OtsPoint3d[] coordsHalf2 = new OtsPoint3d[127];
528 for (int i = 0; i < coordsHalf2.length; i++)
529 {
530 double angle = Math.PI + Math.PI * (i) / (coordsHalf2.length - 1);
531 coordsHalf2[i] = new OtsPoint3d(radius * Math.cos(angle), radius * Math.sin(angle), 0);
532 }
533 List<Lane> lanes2 = new LaneFactory(network, nodeA, nodeB, DefaultsNl.FREEWAY, sim, LaneKeepingPolicy.KEEPLEFT,
534 DefaultsNl.VEHICLE, new OtsLine3d(coordsHalf2))
535 .leftToRight(0.0, Length.instantiateSI(3.5), DefaultsRoadNl.FREEWAY, speedLimit).addLanes(Type.DASHED)
536 .getLanes();
537
538
539 PerceptionFactory perceptionFactory = new LmrsStrategiesPerceptionFactory();
540
541 ParameterFactoryByType parameterFactory = new ParameterFactoryByType();
542 parameterFactory.addParameter(Tailgating.RHO, 0.0);
543 parameterFactory.addParameter(DefaultsNl.CAR, LmrsParameters.SOCIO, 0.5);
544 parameterFactory.addParameter(DefaultsNl.TRUCK, LmrsParameters.SOCIO, 1.0);
545 parameterFactory.addParameter(DefaultsNl.CAR, LmrsParameters.VGAIN, new Speed(35.0, SpeedUnit.KM_PER_HOUR));
546 parameterFactory.addParameter(DefaultsNl.TRUCK, LmrsParameters.VGAIN, new Speed(50.0, SpeedUnit.KM_PER_HOUR));
547 parameterFactory.addParameter(ParameterTypes.TMAX, Duration.instantiateSI(1.6));
548 parameterFactory.addParameter(DefaultsNl.CAR, ParameterTypes.FSPEED,
549 new DistNormal(this.stream, 123.7 / 120.0, 12.0 / 120.0));
550 parameterFactory.addParameter(DefaultsNl.TRUCK, ParameterTypes.A, Acceleration.instantiateSI(0.4));
551 parameterFactory.addParameter(DefaultsNl.TRUCK, ParameterTypes.FSPEED, 1.0);
552 for (GtuType gtuType : new GtuType[] {DefaultsNl.CAR, DefaultsNl.TRUCK})
553 {
554
555 Set<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
556 Set<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
557 Set<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
558 mandatoryIncentives.add(new IncentiveRoute());
559 voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
560 voluntaryIncentives.add(new IncentiveKeep());
561 voluntaryIncentives.add(new IncentiveSocioSpeed());
562 if (gtuType.equals(DefaultsNl.TRUCK))
563 {
564 voluntaryIncentives.add(new IncentiveStayRight());
565 }
566
567 CarFollowingModelFactory<?> cfFactory =
568 gtuType.equals(DefaultsNl.CAR) ? new SocioIDMFactory() : new IdmPlusFactory(this.stream);
569
570 Tailgating tlgt = Tailgating.PRESSURE;
571
572 LaneBasedStrategicalPlannerFactory<?> laneBasedStrategicalPlannerFactory =
573 new LaneBasedStrategicalRoutePlannerFactory(new LmrsFactory(cfFactory, perceptionFactory,
574 Synchronization.PASSIVE, Cooperation.PASSIVE, GapAcceptance.INFORMED, tlgt, mandatoryIncentives,
575 voluntaryIncentives, accelerationIncentives), parameterFactory);
576 this.factories.put(gtuType, laneBasedStrategicalPlannerFactory);
577 }
578 for (int i = 0; i < lanes1.size(); i++)
579 {
580 Length pos = Length.instantiateSI(10.0);
581 Length gap = lanes1.get(i).getLength().plus(lanes2.get(i).getLength()).divide(this.gtuNum / 2);
582 for (int j = 0; j < 2; j++)
583 {
584 Lane lane = j == 0 ? lanes1.get(i) : lanes2.get(i);
585 while (true)
586 {
587 GtuType gtuType;
588 if (i == 0)
589 {
590 gtuType = DefaultsNl.CAR;
591 }
592 else
593 {
594 gtuType = this.stream.nextDouble() < 2 * this.truckFraction ? DefaultsNl.TRUCK : DefaultsNl.CAR;
595 }
596
597 Speed initialSpeed = Speed.ZERO;
598
599 createGtu(lane, pos, gtuType, initialSpeed, network);
600
601 pos = pos.plus(gap);
602 if (pos.si > lane.getLength().si)
603 {
604 pos = pos.minus(lane.getLength());
605 break;
606 }
607 }
608 }
609 }
610
611 this.nextGtuType = this.stream.nextDouble() < this.truckFraction ? DefaultsNl.TRUCK : DefaultsNl.CAR;
612 sim.scheduleEventNow(this, "checkVehicleNumber", new Object[] {});
613
614 return network;
615 }
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630 public void createGtu(final Lane lane, final Length pos, final GtuType gtuType, final Speed initialSpeed,
631 final RoadNetwork net)
632 throws NamingException, GtuException, NetworkException, SimRuntimeException, OtsGeometryException
633 {
634 GtuCharacteristics gtuCharacteristics = Try.assign(() -> GtuType.defaultCharacteristics(gtuType, net, this.stream),
635 "Exception while applying default GTU characteristics.");
636
637 LaneBasedGtu gtu = new LaneBasedGtu("" + (++this.gtuIdNum), gtuType, gtuCharacteristics.getLength(),
638 gtuCharacteristics.getWidth(), gtuCharacteristics.getMaximumSpeed(), gtuCharacteristics.getFront(), net);
639 gtu.setMaximumAcceleration(gtuCharacteristics.getMaximumAcceleration());
640 gtu.setMaximumDeceleration(gtuCharacteristics.getMaximumDeceleration());
641 gtu.setNoLaneChangeDistance(Length.instantiateSI(50));
642 gtu.setInstantaneousLaneChange(true);
643
644
645 LaneBasedStrategicalPlanner strategicalPlanner = this.factories.get(gtuType).create(gtu, null, null, null);
646
647
648 Set<LanePosition> initialPositions = new LinkedHashSet<>(1);
649 initialPositions.add(new LanePosition(lane, pos));
650 if (pos.plus(gtu.getFront().getDx()).gt(lane.getLength()))
651 {
652 Lane nextLane = lane.nextLanes(gtuType).iterator().next();
653 Length nextPos = pos.minus(lane.getLength());
654 initialPositions.add(new LanePosition(nextLane, nextPos));
655 }
656 if (pos.plus(gtu.getRear().getDx()).lt0())
657 {
658 Lane prevLane = lane.prevLanes(gtuType).iterator().next();
659 Length prevPos = prevLane.getLength().plus(pos.plus(gtu.getRear().getDx()));
660 initialPositions.add(new LanePosition(prevLane, prevPos));
661 }
662 gtu.init(strategicalPlanner, initialPositions, initialSpeed);
663
664 if (this.kmplcListener != null)
665 {
666 Try.execute(() -> gtu.addListener(this.kmplcListener, LaneBasedGtu.LANE_CHANGE_EVENT),
667 "Exception while adding lane change listener");
668 }
669 }
670
671
672 class SocioIDMFactory implements CarFollowingModelFactory<IdmPlus>
673 {
674
675 @Override
676 public Parameters getParameters() throws ParameterException
677 {
678 ParameterSet parameters = new ParameterSet();
679 parameters.setDefaultParameters(AbstractIdm.class);
680 return parameters;
681 }
682
683
684 @Override
685 public IdmPlus generateCarFollowingModel()
686 {
687 return new IdmPlus(AbstractIdm.HEADWAY, new SocioDesiredSpeed(AbstractIdm.DESIRED_SPEED));
688 }
689 }
690
691
692 class LmrsStrategiesPerceptionFactory implements PerceptionFactory
693 {
694
695 @Override
696 public LanePerception generatePerception(final LaneBasedGtu gtu)
697 {
698 LanePerception perception = new CategoricalLanePerception(gtu);
699 perception.addPerceptionCategory(new DirectEgoPerception<>(perception));
700 perception.addPerceptionCategory(new DirectInfrastructurePerception(perception));
701 perception.addPerceptionCategory(new DirectNeighborsPerception(perception, HeadwayGtuType.WRAP));
702 perception.addPerceptionCategory(new AnticipationTrafficPerception(perception));
703 return perception;
704 }
705
706
707 @Override
708 public Parameters getParameters() throws ParameterException
709 {
710 return new ParameterSet().setDefaultParameter(ParameterTypes.LOOKAHEAD)
711 .setDefaultParameter(ParameterTypes.LOOKBACKOLD).setDefaultParameter(ParameterTypes.PERCEPTION)
712 .setDefaultParameter(ParameterTypes.LOOKBACK);
713 }
714 }
715
716 }