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