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