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