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