1 package org.opentrafficsim.demo.carFollowing;
2
3 import java.awt.Color;
4 import java.awt.Container;
5 import java.awt.Frame;
6 import java.awt.geom.Rectangle2D;
7 import java.rmi.RemoteException;
8 import java.util.ArrayList;
9 import java.util.HashSet;
10 import java.util.LinkedHashSet;
11 import java.util.List;
12 import java.util.Set;
13
14 import javax.naming.NamingException;
15 import javax.swing.JPanel;
16
17 import org.djunits.unit.LengthUnit;
18 import org.djunits.unit.SpeedUnit;
19 import org.djunits.unit.TimeUnit;
20 import org.djunits.unit.UNITS;
21 import org.djunits.value.vdouble.scalar.Acceleration;
22 import org.djunits.value.vdouble.scalar.DoubleScalar;
23 import org.djunits.value.vdouble.scalar.Duration;
24 import org.djunits.value.vdouble.scalar.Length;
25 import org.djunits.value.vdouble.scalar.Speed;
26 import org.djunits.value.vdouble.scalar.Time;
27 import org.opentrafficsim.base.modelproperties.CompoundProperty;
28 import org.opentrafficsim.base.modelproperties.ContinuousProperty;
29 import org.opentrafficsim.base.modelproperties.ProbabilityDistributionProperty;
30 import org.opentrafficsim.base.modelproperties.Property;
31 import org.opentrafficsim.base.modelproperties.PropertyException;
32 import org.opentrafficsim.base.modelproperties.SelectionProperty;
33 import org.opentrafficsim.core.distributions.Distribution;
34 import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
35 import org.opentrafficsim.core.distributions.Generator;
36 import org.opentrafficsim.core.distributions.ProbabilityException;
37 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
38 import org.opentrafficsim.core.dsol.OTSModelInterface;
39 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
40 import org.opentrafficsim.core.geometry.OTSGeometryException;
41 import org.opentrafficsim.core.geometry.OTSPoint3D;
42 import org.opentrafficsim.core.gtu.GTU;
43 import org.opentrafficsim.core.gtu.GTUDirectionality;
44 import org.opentrafficsim.core.gtu.GTUException;
45 import org.opentrafficsim.core.gtu.GTUType;
46 import org.opentrafficsim.core.gtu.animation.GTUColorer;
47 import org.opentrafficsim.core.gtu.animation.SwitchableGTUColorer;
48 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
49 import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
50 import org.opentrafficsim.core.idgenerator.IdGenerator;
51 import org.opentrafficsim.core.network.LongitudinalDirectionality;
52 import org.opentrafficsim.core.network.Network;
53 import org.opentrafficsim.core.network.NetworkException;
54 import org.opentrafficsim.core.network.Node;
55 import org.opentrafficsim.core.network.OTSNetwork;
56 import org.opentrafficsim.core.network.OTSNode;
57 import org.opentrafficsim.core.network.route.FixedRouteGenerator;
58 import org.opentrafficsim.core.network.route.ProbabilisticRouteGenerator;
59 import org.opentrafficsim.core.network.route.Route;
60 import org.opentrafficsim.core.network.route.RouteGenerator;
61 import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
62 import org.opentrafficsim.graphs.LaneBasedGTUSampler;
63 import org.opentrafficsim.graphs.TrajectoryPlot;
64 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
65 import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
66 import org.opentrafficsim.road.gtu.lane.AbstractLaneBasedGTU;
67 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
68 import org.opentrafficsim.road.gtu.lane.LaneBasedTemplateGTUType;
69 import org.opentrafficsim.road.gtu.lane.LaneBasedTemplateGTUTypeDistribution;
70 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlannerFactory;
71 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory;
72 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingTacticalPlanner;
73 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingTacticalPlannerFactory;
74 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
75 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
76 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMOld;
77 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
78 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
79 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.AbstractLaneChangeModel;
80 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Altruistic;
81 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
82 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
83 import org.opentrafficsim.road.gtu.lane.tactical.toledo.ToledoFactory;
84 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
85 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
86 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
87 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
88 import org.opentrafficsim.road.modelproperties.IDMPropertySet;
89 import org.opentrafficsim.road.network.factory.LaneFactory;
90 import org.opentrafficsim.road.network.lane.CrossSectionLink;
91 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
92 import org.opentrafficsim.road.network.lane.Lane;
93 import org.opentrafficsim.road.network.lane.LaneType;
94 import org.opentrafficsim.road.network.lane.changing.OvertakingConditions;
95 import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
96 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
97 import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
98
99 import nl.tudelft.simulation.dsol.SimRuntimeException;
100 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
101 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
102 import nl.tudelft.simulation.jstats.distributions.DistContinuous;
103 import nl.tudelft.simulation.jstats.distributions.DistErlang;
104 import nl.tudelft.simulation.jstats.distributions.DistUniform;
105 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
106 import nl.tudelft.simulation.jstats.streams.StreamInterface;
107
108
109
110
111
112
113
114
115
116
117
118 public class XMLNetworks extends AbstractWrappableAnimation implements UNITS
119 {
120
121 private static final long serialVersionUID = 20160422L;
122
123
124 private XMLNetworkModel model;
125
126
127
128
129 public XMLNetworks()
130 {
131 this.properties.add(new SelectionProperty(
132 "Network", "Network", "Network", new String[] { "Merge 1 plus 1 into 1", "Merge 2 plus 1 into 2",
133 "Merge 2 plus 2 into 4", "Split 1 into 1 plus 1", "Split 2 into 1 plus 2", "Split 4 into 2 plus 2" },
134 0, false, 0));
135 this.properties.add(new SelectionProperty("TacticalPlanner", "Tactical planner",
136 "<html>The tactical planner determines if a lane change is desired and possible.</html>",
137 new String[] { "MOBIL/IDM", "DIRECTED/IDM", "LMRS", "Toledo" }, 0, false, 600));
138 this.properties.add(new SelectionProperty("LaneChanging", "Lane changing",
139 "<html>The lane change friendliness (if used -- eg just for MOBIL.</html>",
140 new String[] { "Egoistic", "Altruistic" }, 0, false, 600));
141 this.properties.add(new ContinuousProperty("FlowPerInputLane", "Flow per input lane", "Traffic flow per input lane",
142 500d, 0d, 3000d, "%.0f veh/h", false, 1));
143 }
144
145
146 @Override
147 public final void stopTimersThreads()
148 {
149 super.stopTimersThreads();
150 this.model = null;
151 }
152
153
154 @Override
155 protected final Rectangle2D.Double makeAnimationRectangle()
156 {
157 return new Rectangle2D.Double(-50, -300, 1300, 600);
158 }
159
160
161 @Override
162 protected final OTSModelInterface makeModel(final GTUColorer colorer)
163 {
164 this.model = new XMLNetworkModel(this.savedUserModifiedProperties, colorer);
165 return this.model;
166 }
167
168
169 @Override
170 protected final JPanel makeCharts(SimpleSimulatorInterface simulator)
171 {
172 int graphCount = this.model.pathCount();
173 int columns = 1;
174 int rows = 0 == columns ? 0 : (int) Math.ceil(graphCount * 1.0 / columns);
175 TablePanel charts = new TablePanel(columns, rows);
176 for (int graphIndex = 0; graphIndex < graphCount; graphIndex++)
177 {
178 TrajectoryPlot tp = new TrajectoryPlot("Trajectories on lane " + (graphIndex + 1), new Duration(0.5, SECOND),
179 this.model.getPath(graphIndex), simulator);
180 tp.setTitle("Trajectory Graph");
181 tp.setExtendedState(Frame.MAXIMIZED_BOTH);
182 LaneBasedGTUSampler graph = tp;
183 Container container = tp.getContentPane();
184 charts.setCell(container, graphIndex % columns, graphIndex / columns);
185 this.model.getPlots().add(graph);
186 }
187 return charts;
188 }
189
190
191 @Override
192 public final String shortName()
193 {
194 return "Test networks";
195 }
196
197
198 @Override
199 public final String description()
200 {
201 return "<html><h1>Test Networks</h1>Prove that the test networks can be constructed and rendered on screen "
202 + "and that a mix of cars and trucks can run on them.<br>On the statistics tab, a trajectory plot "
203 + "is generated for each lane.</html>";
204 }
205
206 }
207
208
209
210
211
212
213
214
215
216
217
218 class XMLNetworkModel implements OTSModelInterface, UNITS
219 {
220
221 private static final long serialVersionUID = 20150304L;
222
223
224 private OTSDEVSSimulatorInterface simulator;
225
226
227 private final Network network = new OTSNetwork("network");
228
229
230 private List<LaneBasedGTUSampler> plots = new ArrayList<>();
231
232
233 private List<Property<?>> properties = null;
234
235
236 private List<List<Lane>> paths = new ArrayList<>();
237
238
239 private Duration averageHeadway;
240
241
242 private Duration minimumHeadway;
243
244
245 DistContinuous headwayGenerator;
246
247
248 private Speed speedLimit = new Speed(60, KM_PER_HOUR);
249
250
251
252
253
254 GTUType gtuType = new GTUType("Car");
255
256
257 private GTUFollowingModelOld carFollowingModelCars;
258
259
260 private GTUFollowingModelOld carFollowingModelTrucks;
261
262
263 AbstractLaneChangeModel laneChangeModel = new Egoistic();
264
265
266 private double carProbability;
267
268
269
270
271
272
273
274
275 private RouteGenerator routeGenerator;
276
277
278 private final GTUColorer gtuColorer;
279
280
281 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
282
283
284 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
285
286
287 private IdGenerator idGenerator = new IdGenerator("");
288
289
290
291
292
293 XMLNetworkModel(final List<Property<?>> userModifiedProperties, final GTUColorer gtuColorer)
294 {
295 this.gtuColorer = gtuColorer;
296 if (this.gtuColorer instanceof SwitchableGTUColorer)
297 {
298
299
300
301 }
302 this.properties = userModifiedProperties;
303 }
304
305
306
307
308
309 public final List<Lane> getPath(final int index)
310 {
311 return this.paths.get(index);
312 }
313
314
315
316
317
318 public final int pathCount()
319 {
320 return this.paths.size();
321 }
322
323
324
325
326 public final List<LaneBasedGTUSampler> getPlots()
327 {
328 return this.plots;
329 }
330
331
332 @Override
333 public final void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
334 throws SimRuntimeException, RemoteException
335 {
336 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
337 try
338 {
339 OTSNode from = new OTSNode(this.network, "From", new OTSPoint3D(0, 0, 0));
340 OTSNode end = new OTSNode(this.network, "End", new OTSPoint3D(2000, 0, 0));
341 OTSNode from2a = new OTSNode(this.network, "From2a", new OTSPoint3D(0, -50, 0));
342 OTSNode from2b = new OTSNode(this.network, "From2b", new OTSPoint3D(490, -2, 0));
343 OTSNode firstVia = new OTSNode(this.network, "Via1", new OTSPoint3D(500, 0, 0));
344 OTSNode end2a = new OTSNode(this.network, "End2a", new OTSPoint3D(1020, -2, 0));
345 OTSNode end2b = new OTSNode(this.network, "End2b", new OTSPoint3D(2000, -50, 0));
346 OTSNode secondVia = new OTSNode(this.network, "Via2", new OTSPoint3D(1000, 0, 0));
347 CompoundProperty cp = null;
348 try
349 {
350 cp = new CompoundProperty("", "", "", this.properties, false, 0);
351 }
352 catch (PropertyException exception2)
353 {
354 exception2.printStackTrace();
355 }
356 String networkType = (String) cp.findByKey("Network").getValue();
357 boolean merge = networkType.startsWith("M");
358 int lanesOnMain = Integer.parseInt(networkType.split(" ")[merge ? 1 : 5]);
359 int lanesOnBranch = Integer.parseInt(networkType.split(" ")[3]);
360 int lanesOnCommon = lanesOnMain + lanesOnBranch;
361 int lanesOnCommonCompressed = Integer.parseInt(networkType.split(" ")[merge ? 5 : 1]);
362
363 Set<GTUType> compatibility = new HashSet<>();
364 compatibility.add(this.gtuType);
365 LaneType laneType = new LaneType("CarLane", compatibility);
366
367 String carFollowingModelName = null;
368 CompoundProperty propertyContainer = new CompoundProperty("", "", "", this.properties, false, 0);
369 Property<?> cfmp = propertyContainer.findByKey("CarFollowingModel");
370 if (null == cfmp)
371 {
372 throw new Error("Cannot find \"Car following model\" property");
373 }
374 if (cfmp instanceof SelectionProperty)
375 {
376 carFollowingModelName = ((SelectionProperty) cfmp).getValue();
377 }
378 else
379 {
380 throw new Error("\"Car following model\" property has wrong type");
381 }
382
383
384 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
385 {
386 if (ap instanceof CompoundProperty)
387 {
388 cp = (CompoundProperty) ap;
389 if (ap.getKey().contains("IDM"))
390 {
391
392 Acceleration a = IDMPropertySet.getA(cp);
393 Acceleration b = IDMPropertySet.getB(cp);
394 Length s0 = IDMPropertySet.getS0(cp);
395 Duration tSafe = IDMPropertySet.getTSafe(cp);
396 GTUFollowingModelOld gtuFollowingModel = null;
397 if (carFollowingModelName.equals("IDM"))
398 {
399 gtuFollowingModel = new IDMOld(a, b, s0, tSafe, 1.0);
400 }
401 else if (carFollowingModelName.equals("IDM+"))
402 {
403 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
404 }
405 else
406 {
407 throw new Error("Unknown gtu following model: " + carFollowingModelName);
408 }
409 if (ap.getKey().contains("Car"))
410 {
411 this.carFollowingModelCars = gtuFollowingModel;
412 }
413 else if (ap.getKey().contains("Truck"))
414 {
415 this.carFollowingModelTrucks = gtuFollowingModel;
416 }
417 else
418 {
419 throw new Error("Cannot determine gtu type for " + ap.getKey());
420 }
421 }
422 }
423 }
424
425
426 cfmp = propertyContainer.findByKey("LaneChanging");
427 if (null == cfmp)
428 {
429 throw new Error("Cannot find \"Lane changing\" property");
430 }
431 if (cfmp instanceof SelectionProperty)
432 {
433 String laneChangeModelName = ((SelectionProperty) cfmp).getValue();
434 if ("Egoistic".equals(laneChangeModelName))
435 {
436 this.laneChangeModel = new Egoistic();
437 }
438 else if ("Altruistic".equals(laneChangeModelName))
439 {
440 this.laneChangeModel = new Altruistic();
441 }
442 else
443 {
444 throw new Error("Lane changing " + laneChangeModelName + " not implemented");
445 }
446 }
447 else
448 {
449 throw new Error("\"Lane changing\" property has wrong type");
450 }
451
452 if (merge)
453 {
454
455 ArrayList<Node> mainRouteNodes = new ArrayList<>();
456 mainRouteNodes.add(firstVia);
457 mainRouteNodes.add(secondVia);
458 mainRouteNodes.add(end);
459 Route mainRoute = new Route("main", mainRouteNodes);
460 this.routeGenerator = new FixedRouteGenerator(mainRoute);
461 }
462 else
463 {
464
465 List<FrequencyAndObject<Route>> routeProbabilities = new ArrayList<>();
466
467 ArrayList<Node> mainRouteNodes = new ArrayList<>();
468 mainRouteNodes.add(firstVia);
469 mainRouteNodes.add(secondVia);
470 mainRouteNodes.add(end);
471 Route mainRoute = new Route("main", mainRouteNodes);
472 routeProbabilities.add(new FrequencyAndObject<>(lanesOnMain, mainRoute));
473
474 ArrayList<Node> sideRouteNodes = new ArrayList<>();
475 sideRouteNodes.add(firstVia);
476 sideRouteNodes.add(secondVia);
477 sideRouteNodes.add(end2a);
478 sideRouteNodes.add(end2b);
479 Route sideRoute = new Route("side", sideRouteNodes);
480 routeProbabilities.add(new FrequencyAndObject<>(lanesOnBranch, sideRoute));
481 try
482 {
483 this.routeGenerator = new ProbabilisticRouteGenerator(routeProbabilities, new MersenneTwister(1234));
484 }
485 catch (ProbabilityException exception)
486 {
487 exception.printStackTrace();
488 }
489 }
490
491
492 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
493 {
494 if (ap instanceof SelectionProperty)
495 {
496 SelectionProperty sp = (SelectionProperty) ap;
497 if ("TacticalPlanner".equals(sp.getKey()))
498 {
499 String tacticalPlannerName = sp.getValue();
500 if ("IDM".equals(tacticalPlannerName))
501 {
502 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
503 new LaneBasedGTUFollowingTacticalPlannerFactory(this.carFollowingModelCars),
504 this.routeGenerator);
505 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
506 new LaneBasedGTUFollowingTacticalPlannerFactory(this.carFollowingModelTrucks),
507 this.routeGenerator);
508 }
509 else if ("MOBIL/IDM".equals(tacticalPlannerName))
510 {
511 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
512 new LaneBasedCFLCTacticalPlannerFactory(this.carFollowingModelCars, this.laneChangeModel),
513 this.routeGenerator);
514 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
515 new LaneBasedCFLCTacticalPlannerFactory(this.carFollowingModelTrucks, this.laneChangeModel),
516 this.routeGenerator);
517 }
518 else if ("DIRECTED/IDM".equals(tacticalPlannerName))
519 {
520 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
521 new LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory(this.carFollowingModelCars),
522 this.routeGenerator);
523 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
524 new LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory(this.carFollowingModelTrucks),
525 this.routeGenerator);
526 }
527 else if ("LMRS".equals(tacticalPlannerName))
528 {
529
530 BehavioralCharacteristics defaultBehavioralCFCharacteristics = new BehavioralCharacteristics();
531 defaultBehavioralCFCharacteristics.setDefaultParameters(AbstractIDM.class);
532 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
533 new LMRSFactory(new IDMPlusFactory(), defaultBehavioralCFCharacteristics),
534 this.routeGenerator);
535 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
536 new LMRSFactory(new IDMPlusFactory(), defaultBehavioralCFCharacteristics),
537 this.routeGenerator);
538 }
539 else if ("Toledo".equals(tacticalPlannerName))
540 {
541 this.strategicalPlannerGeneratorCars =
542 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory(), this.routeGenerator);
543 this.strategicalPlannerGeneratorTrucks =
544 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory(), this.routeGenerator);
545 }
546 else
547 {
548 throw new Error("Don't know how to create a " + tacticalPlannerName + " tactical planner");
549 }
550 }
551
552 }
553 else if (ap instanceof ProbabilityDistributionProperty)
554 {
555 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) ap;
556 String modelName = ap.getKey();
557 if (modelName.equals("TrafficComposition"))
558 {
559 this.carProbability = pdp.getValue()[0];
560 }
561 }
562 else if (ap instanceof ContinuousProperty)
563 {
564 ContinuousProperty contP = (ContinuousProperty) ap;
565 if (contP.getKey().startsWith("Flow"))
566 {
567 this.averageHeadway = new Duration(3600.0 / contP.getValue(), SECOND);
568 this.minimumHeadway = new Duration(3, SECOND);
569 this.headwayGenerator = new DistErlang(new MersenneTwister(1234), 4,
570 DoubleScalar.minus(this.averageHeadway, this.minimumHeadway).getSI());
571 }
572 }
573 else if (ap instanceof CompoundProperty)
574 {
575 CompoundProperty compoundProperty = (CompoundProperty) ap;
576 if (ap.getKey().equals("Output"))
577 {
578 continue;
579 }
580 if (ap.getKey().contains("IDM"))
581 {
582 Acceleration a = IDMPropertySet.getA(compoundProperty);
583 Acceleration b = IDMPropertySet.getB(compoundProperty);
584 Length s0 = IDMPropertySet.getS0(compoundProperty);
585 Duration tSafe = IDMPropertySet.getTSafe(compoundProperty);
586 GTUFollowingModelOld gtuFollowingModel = null;
587 if (carFollowingModelName.equals("IDM"))
588 {
589 gtuFollowingModel = new IDMOld(a, b, s0, tSafe, 1.0);
590 }
591 else if (carFollowingModelName.equals("IDM+"))
592 {
593 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
594 }
595 else
596 {
597 throw new Error("Unknown gtu following model: " + carFollowingModelName);
598 }
599 if (ap.getKey().contains("Car"))
600 {
601 this.carFollowingModelCars = gtuFollowingModel;
602 }
603 else if (ap.getKey().contains("Truck"))
604 {
605 this.carFollowingModelTrucks = gtuFollowingModel;
606 }
607 else
608 {
609 throw new Error("Cannot determine gtu type for " + ap.getKey());
610 }
611 }
612 }
613 }
614
615 if (merge)
616 {
617 setupGenerator(LaneFactory.makeMultiLane(this.network, "From2a to From2b", from2a, from2b, null, lanesOnBranch,
618 0, lanesOnCommon - lanesOnBranch, laneType, this.speedLimit, this.simulator,
619 LongitudinalDirectionality.DIR_PLUS));
620 LaneFactory.makeMultiLaneBezier(this.network, "From2b to FirstVia", from2a, from2b, firstVia, secondVia,
621 lanesOnBranch, lanesOnCommon - lanesOnBranch, lanesOnCommon - lanesOnBranch, laneType, this.speedLimit,
622 this.simulator, LongitudinalDirectionality.DIR_PLUS);
623 }
624 else
625 {
626 LaneFactory.makeMultiLaneBezier(this.network, "SecondVia to end2a", firstVia, secondVia, end2a, end2b,
627 lanesOnBranch, lanesOnCommon - lanesOnBranch, lanesOnCommon - lanesOnBranch, laneType, this.speedLimit,
628 this.simulator, LongitudinalDirectionality.DIR_PLUS);
629 setupSink(LaneFactory.makeMultiLane(this.network, "end2a to end2b", end2a, end2b, null, lanesOnBranch,
630 lanesOnCommon - lanesOnBranch, 0, laneType, this.speedLimit, this.simulator,
631 LongitudinalDirectionality.DIR_PLUS), laneType);
632 }
633
634 Lane[] startLanes = LaneFactory.makeMultiLane(this.network, "From to FirstVia", from, firstVia, null,
635 merge ? lanesOnMain : lanesOnCommonCompressed, laneType, this.speedLimit, this.simulator,
636 LongitudinalDirectionality.DIR_PLUS);
637 setupGenerator(startLanes);
638 Lane[] common = LaneFactory.makeMultiLane(this.network, "FirstVia to SecondVia", firstVia, secondVia, null,
639 lanesOnCommon, laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
640 if (merge)
641 {
642 for (int i = lanesOnCommonCompressed; i < lanesOnCommon; i++)
643 {
644 setupBlock(common[i]);
645 }
646 }
647 setupSink(LaneFactory.makeMultiLane(this.network, "SecondVia to end", secondVia, end, null,
648 merge ? lanesOnCommonCompressed : lanesOnMain, laneType, this.speedLimit, this.simulator,
649 LongitudinalDirectionality.DIR_PLUS), laneType);
650
651 for (int index = 0; index < lanesOnCommon; index++)
652 {
653 this.paths.add(new ArrayList<Lane>());
654 Lane lane = common[index];
655
656 while (lane.prevLanes(this.gtuType).size() > 0)
657 {
658 if (lane.prevLanes(this.gtuType).size() > 1)
659 {
660 throw new NetworkException("This network should not have lane merge points");
661 }
662 lane = lane.prevLanes(this.gtuType).keySet().iterator().next();
663 }
664
665 while (true)
666 {
667 this.paths.get(index).add(lane);
668 int branching = lane.nextLanes(this.gtuType).size();
669 if (branching == 0)
670 {
671 break;
672 }
673 if (branching > 1)
674 {
675 throw new NetworkException("This network should not have lane split points");
676 }
677 lane = lane.nextLanes(this.gtuType).keySet().iterator().next();
678 }
679 }
680 this.simulator.scheduleEventAbs(new Time(0.999, SECOND), this, this, "drawGraphs", null);
681 }
682 catch (NamingException | NetworkException | GTUException | OTSGeometryException | ProbabilityException
683 | PropertyException | ParameterException exception1)
684 {
685 exception1.printStackTrace();
686 }
687 }
688
689
690
691
692
693
694
695
696
697
698 private Lane[] setupGenerator(final Lane[] lanes)
699 throws SimRuntimeException, GTUException, ProbabilityException, ParameterException
700 {
701 for (Lane lane : lanes)
702 {
703 makeGenerator(lane);
704
705
706
707
708 }
709 return lanes;
710 }
711
712
713
714
715
716
717
718
719
720
721 private LaneBasedGTUGenerator makeGenerator(final Lane lane)
722 throws GTUException, SimRuntimeException, ProbabilityException, ParameterException
723 {
724 StreamInterface stream = new MersenneTwister(1234);
725 Distribution<LaneBasedTemplateGTUType> distribution = new Distribution<>(stream);
726 Length initialPosition = new Length(16, METER);
727 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
728 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
729
730 LaneBasedTemplateGTUType template = makeTemplate(stream, lane,
731 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(stream, 3, 6), METER),
732 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(stream, 1.6, 2.0), METER),
733 new ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit>(new DistUniform(stream, 140, 180), KM_PER_HOUR),
734 new ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit>(new DistUniform(stream, 100, 125), KM_PER_HOUR),
735 initialPositions, this.strategicalPlannerGeneratorCars);
736
737 distribution.add(new FrequencyAndObject<>(this.carProbability, template));
738 template = makeTemplate(stream, lane,
739 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(stream, 8, 14), METER),
740 new ContinuousDistDoubleScalar.Rel<Length, LengthUnit>(new DistUniform(stream, 2.0, 2.5), METER),
741 new ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit>(new DistUniform(stream, 100, 140), KM_PER_HOUR),
742 new ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit>(new DistUniform(stream, 80, 90), KM_PER_HOUR),
743 initialPositions, this.strategicalPlannerGeneratorTrucks);
744
745 distribution.add(new FrequencyAndObject<>(1.0 - this.carProbability, template));
746 LaneBasedTemplateGTUTypeDistribution templateDistribution = new LaneBasedTemplateGTUTypeDistribution(distribution);
747 LaneBasedGTUGenerator.RoomChecker roomChecker = new CanPlaceDemoCode();
748 return new LaneBasedGTUGenerator(lane.getId(), new Generator<Duration>()
749 {
750 public Duration draw()
751 {
752 return new Duration(XMLNetworkModel.this.headwayGenerator.draw(), TimeUnit.SECOND);
753 }
754 }, Long.MAX_VALUE, new Time(0, TimeUnit.SI), new Time(Double.MAX_VALUE, TimeUnit.SI), this.gtuColorer,
755 templateDistribution, initialPositions, (OTSNetwork) this.network,
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780 roomChecker);
781 }
782
783
784
785
786
787
788
789
790
791
792
793
794
795 LaneBasedTemplateGTUType makeTemplate(final StreamInterface stream, final Lane lane,
796 final ContinuousDistDoubleScalar.Rel<Length, LengthUnit> lengthDistribution,
797 final ContinuousDistDoubleScalar.Rel<Length, LengthUnit> widthDistribution,
798 final ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> maximumSpeedDistribution,
799 final ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> initialSpeedDistribution,
800 final Set<DirectedLanePosition> initialPositions,
801 final LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactory) throws GTUException
802 {
803 return new LaneBasedTemplateGTUType(this.gtuType, this.idGenerator, new Generator<Length>()
804 {
805 public Length draw()
806 {
807 return lengthDistribution.draw();
808 }
809 }, new Generator<Length>()
810 {
811 public Length draw()
812 {
813 return widthDistribution.draw();
814 }
815 }, new Generator<Speed>()
816 {
817 public Speed draw()
818 {
819 return maximumSpeedDistribution.draw();
820 }
821 }, this.simulator,
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839 strategicalPlannerFactory, initialPositions, new Generator<Speed>()
840 {
841 public Speed draw()
842 {
843 return initialSpeedDistribution.draw();
844 }
845 }, (OTSNetwork) this.network);
846
847 }
848
849
850
851
852
853
854
855
856
857 private Lane[] setupSink(final Lane[] lanes, final LaneType laneType) throws NetworkException, OTSGeometryException
858 {
859 CrossSectionLink link = lanes[0].getParentLink();
860 Node to = link.getEndNode();
861 Node from = link.getStartNode();
862 double endLinkLength = 50;
863 double endX = to.getPoint().x + (endLinkLength / link.getLength().getSI()) * (to.getPoint().x - from.getPoint().x);
864 double endY = to.getPoint().y + (endLinkLength / link.getLength().getSI()) * (to.getPoint().y - from.getPoint().y);
865 Node end = new OTSNode(this.network, link.getId() + "END", new OTSPoint3D(endX, endY, to.getPoint().z));
866 CrossSectionLink endLink = LaneFactory.makeLink(this.network, link.getId() + "endLink", to, end, null,
867 LongitudinalDirectionality.DIR_PLUS);
868 for (Lane lane : lanes)
869 {
870
871 Lane sinkLane = new Lane(endLink, lane.getId() + "." + "sinkLane", lane.getLateralCenterPosition(1.0),
872 lane.getLateralCenterPosition(1.0), lane.getWidth(1.0), lane.getWidth(1.0), laneType,
873 LongitudinalDirectionality.DIR_PLUS, this.speedLimit, new OvertakingConditions.LeftAndRight());
874 new SinkSensor(sinkLane, new Length(10.0, METER), this.simulator);
875 }
876 return lanes;
877 }
878
879
880
881
882
883
884
885
886
887
888
889 private Lane setupBlock(final Lane lane)
890 throws NamingException, NetworkException, SimRuntimeException, GTUException, OTSGeometryException
891 {
892 Length initialPosition = lane.getLength();
893 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
894 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
895
896
897
898
899 BehavioralCharacteristics behavioralCharacteristics = DefaultsFactory.getDefaultBehavioralCharacteristics();
900 LaneBasedIndividualGTU block = new LaneBasedIndividualGTU("999999", this.gtuType, new Length(1, METER),
901 lane.getWidth(1), new Speed(0.0, KM_PER_HOUR), this.simulator, (OTSNetwork) this.network);
902 LaneBasedStrategicalPlanner strategicalPlanner = new LaneBasedStrategicalRoutePlanner(behavioralCharacteristics,
903 new LaneBasedGTUFollowingTacticalPlanner(this.carFollowingModelCars, block), block);
904 block.initWithAnimation(strategicalPlanner, initialPositions, new Speed(0.0, KM_PER_HOUR), DefaultCarAnimation.class,
905 this.gtuColorer);
906 return lane;
907 }
908
909
910
911
912 protected final void drawGraphs()
913 {
914 for (LaneBasedGTUSampler plot : this.plots)
915 {
916 plot.reGraph();
917 }
918
919 try
920 {
921 this.simulator.scheduleEventAbs(new Time(this.simulator.getSimulatorTime().get().getSI() + 1, SECOND), this, this,
922 "drawGraphs", null);
923 }
924 catch (SimRuntimeException exception)
925 {
926 exception.printStackTrace();
927 }
928
929 }
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009 @Override
1010 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
1011 {
1012 return this.simulator;
1013 }
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027 private class DirectionGTUColorer implements GTUColorer
1028 {
1029
1030 private List<LegendEntry> legend = new ArrayList<>();
1031
1032
1033 DirectionGTUColorer()
1034 {
1035 super();
1036 this.legend.add(new LegendEntry(Color.RED, "Right", "Go right"));
1037 this.legend.add(new LegendEntry(Color.BLUE, "Main", "Main route"));
1038 }
1039
1040
1041 @Override
1042 public Color getColor(final GTU gtu)
1043 {
1044 AbstractLaneBasedGTU laneBasedGTU = (AbstractLaneBasedGTU) gtu;
1045 Route route = ((LaneBasedStrategicalRoutePlanner) laneBasedGTU.getStrategicalPlanner()).getRoute();
1046 if (route == null)
1047 {
1048 return Color.black;
1049 }
1050 if (route.toString().toLowerCase().contains("end2"))
1051 {
1052 return Color.red;
1053 }
1054 if (route.toString().toLowerCase().contains("end"))
1055 {
1056 return Color.blue;
1057 }
1058 return Color.black;
1059 }
1060
1061
1062 @Override
1063 public List<LegendEntry> getLegend()
1064 {
1065 return this.legend;
1066 }
1067 }
1068
1069 }