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