1 package org.opentrafficsim.demo.carFollowing;
2
3 import java.awt.Color;
4 import java.awt.Container;
5 import java.awt.Frame;
6 import java.io.ByteArrayInputStream;
7 import java.io.IOException;
8 import java.rmi.RemoteException;
9 import java.util.ArrayList;
10 import java.util.List;
11 import java.util.Set;
12
13 import javax.naming.NamingException;
14 import javax.xml.parsers.ParserConfigurationException;
15
16 import org.djunits.unit.LengthUnit;
17 import org.djunits.unit.SpeedUnit;
18 import org.djunits.unit.TimeUnit;
19 import org.djunits.unit.UNITS;
20 import org.djunits.value.ValueException;
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.base.parameters.ParameterException;
34 import org.opentrafficsim.core.distributions.Generator;
35 import org.opentrafficsim.core.dsol.OTSModelInterface;
36 import org.opentrafficsim.core.geometry.OTSGeometryException;
37 import org.opentrafficsim.core.gtu.GTU;
38 import org.opentrafficsim.core.gtu.GTUException;
39 import org.opentrafficsim.core.gtu.GTUType;
40 import org.opentrafficsim.core.gtu.animation.GTUColorer;
41 import org.opentrafficsim.core.network.NetworkException;
42 import org.opentrafficsim.core.network.OTSNetwork;
43 import org.opentrafficsim.core.network.route.Route;
44 import org.opentrafficsim.core.network.route.RouteGenerator;
45 import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
46 import org.opentrafficsim.graphs.LaneBasedGTUSampler;
47 import org.opentrafficsim.graphs.TrajectoryPlot;
48 import org.opentrafficsim.road.animation.AnimationToggles;
49 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUType;
50 import org.opentrafficsim.road.gtu.lane.AbstractLaneBasedGTU;
51 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlannerFactory;
52 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory;
53 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedGTUFollowingTacticalPlannerFactory;
54 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
55 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMOld;
56 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
57 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
58 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.AbstractLaneChangeModel;
59 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Altruistic;
60 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
61 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
62 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
63 import org.opentrafficsim.road.gtu.lane.tactical.toledo.ToledoFactory;
64 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
65 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
66 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner;
67 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
68 import org.opentrafficsim.road.modelproperties.IDMPropertySet;
69 import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
70 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
71 import org.opentrafficsim.road.network.lane.Lane;
72 import org.opentrafficsim.road.network.lane.LaneType;
73 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
74 import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
75 import org.xml.sax.SAXException;
76
77 import nl.tudelft.simulation.dsol.SimRuntimeException;
78 import nl.tudelft.simulation.dsol.gui.swing.TablePanel;
79 import nl.tudelft.simulation.dsol.simtime.SimTimeDoubleUnit;
80 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
81 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
82 import nl.tudelft.simulation.jstats.distributions.DistContinuous;
83 import nl.tudelft.simulation.jstats.distributions.DistErlang;
84 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
85 import nl.tudelft.simulation.jstats.streams.StreamInterface;
86
87
88
89
90
91
92
93
94
95
96
97 public class XMLNetworks2 extends AbstractWrappableAnimation implements UNITS
98 {
99
100 private static final long serialVersionUID = 20160422L;
101
102
103 private XMLNetwork2Model model;
104
105
106
107
108 public XMLNetworks2()
109 {
110 this.properties.add(new SelectionProperty(
111 "Network", "Network", "Network", new String[] { "Merge 1 plus 1 into 1", "Merge 2 plus 1 into 2",
112 "Merge 2 plus 2 into 4", "Split 1 into 1 plus 1", "Split 2 into 1 plus 2", "Split 4 into 2 plus 2" },
113 0, false, 0));
114 this.properties.add(new SelectionProperty("TacticalPlanner", "Tactical planner",
115 "<html>The tactical planner determines if a lane change is desired and possible.</html>",
116 new String[] { "MOBIL/IDM", "DIRECTED/IDM", "LMRS", "Toledo" }, 0, false, 600));
117 this.properties.add(new SelectionProperty("LaneChanging", "Lane changing",
118 "<html>The lane change friendliness (if used -- eg just for MOBIL.</html>",
119 new String[] { "Egoistic", "Altruistic" }, 0, false, 600));
120 this.properties.add(new ContinuousProperty("FlowPerInputLane", "Flow per input lane", "Traffic flow per input lane",
121 500d, 0d, 3000d, "%.0f veh/h", false, 1));
122 }
123
124
125 @Override
126 public final void stopTimersThreads()
127 {
128 super.stopTimersThreads();
129 this.model = null;
130 }
131
132
133 @Override
134 protected final void addAnimationToggles()
135 {
136 AnimationToggles.setTextAnimationTogglesStandard(this);
137 }
138
139
140 @Override
141 protected final OTSModelInterface makeModel()
142 {
143 this.model = new XMLNetwork2Model(this.savedUserModifiedProperties);
144 return this.model;
145 }
146
147
148 @Override
149 protected final void addTabs(final SimpleSimulatorInterface simulator)
150 {
151 int graphCount = this.model.pathCount();
152 int columns = 1;
153 int rows = 0 == columns ? 0 : (int) Math.ceil(graphCount * 1.0 / columns);
154 TablePanel charts = new TablePanel(columns, rows);
155 for (int graphIndex = 0; graphIndex < graphCount; graphIndex++)
156 {
157 TrajectoryPlot tp = new TrajectoryPlot("Trajectories on lane " + (graphIndex + 1), new Duration(0.5, SECOND),
158 this.model.getPath(graphIndex), simulator);
159 tp.setTitle("Trajectory Graph");
160 tp.setExtendedState(Frame.MAXIMIZED_BOTH);
161 LaneBasedGTUSampler graph = tp;
162 Container container = tp.getContentPane();
163 charts.setCell(container, graphIndex % columns, graphIndex / columns);
164 this.model.getPlots().add(graph);
165 }
166 addTab(getTabCount(), "statistics", charts);
167 }
168
169
170 @Override
171 public final String shortName()
172 {
173 return "Test networks - XML version";
174 }
175
176
177 @Override
178 public final String description()
179 {
180 return "<html><h1>Test Networks</h1>Prove that the test networks can be constructed and rendered on screen "
181 + "and that a mix of cars and trucks can run on them.<br>On the statistics tab, a trajectory plot "
182 + "is generated for each lane.</html>";
183 }
184
185 }
186
187
188
189
190
191
192
193
194
195
196
197 class XMLNetwork2Model implements OTSModelInterface, UNITS
198 {
199
200 private static final long serialVersionUID = 20150304L;
201
202
203 private DEVSSimulatorInterface.TimeDoubleUnit simulator;
204
205
206 private final OTSNetwork network = new OTSNetwork("network");
207
208
209 private List<LaneBasedGTUSampler> plots = new ArrayList<>();
210
211
212 private List<Property<?>> properties = null;
213
214
215 private List<List<Lane>> paths = new ArrayList<>();
216
217
218 private Duration averageHeadway;
219
220
221 private Duration minimumHeadway;
222
223
224 DistContinuous headwayGenerator;
225
226
227 private Speed speedLimit = new Speed(60, KM_PER_HOUR);
228
229
230
231
232
233 GTUType gtuType = GTUType.CAR;
234
235
236 private GTUFollowingModelOld carFollowingModelCars;
237
238
239 private GTUFollowingModelOld carFollowingModelTrucks;
240
241
242 AbstractLaneChangeModel laneChangeModel = new Egoistic();
243
244
245 private double carProbability;
246
247
248 private StreamInterface stream = new MersenneTwister(12346);
249
250
251
252
253
254
255
256
257 private RouteGenerator routeGenerator;
258
259
260 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
261
262
263 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
264
265
266
267
268 XMLNetwork2Model(final List<Property<?>> userModifiedProperties)
269 {
270 this.properties = userModifiedProperties;
271 }
272
273
274
275
276
277 public final List<Lane> getPath(final int index)
278 {
279 return this.paths.get(index);
280 }
281
282
283
284
285
286 public final int pathCount()
287 {
288 return this.paths.size();
289 }
290
291
292
293
294 public final List<LaneBasedGTUSampler> getPlots()
295 {
296 return this.plots;
297 }
298
299
300 @Override
301 public final void constructModel(final SimulatorInterface<Time, Duration, SimTimeDoubleUnit> theSimulator)
302 throws SimRuntimeException
303 {
304 this.simulator = (DEVSSimulatorInterface.TimeDoubleUnit) theSimulator;
305 try
306 {
307 CompoundProperty cp = new CompoundProperty("", "", "", this.properties, false, 0);
308 String networkType = (String) cp.findByKey("Network").getValue();
309 boolean merge = networkType.startsWith("M");
310 int lanesOnMain = Integer.parseInt(networkType.split(" ")[merge ? 1 : 5]);
311 int lanesOnBranch = Integer.parseInt(networkType.split(" ")[3]);
312 int lanesOnCommon = lanesOnMain + lanesOnBranch;
313 int lanesOnCommonCompressed = Integer.parseInt(networkType.split(" ")[merge ? 5 : 1]);
314
315 LaneType laneType = LaneType.TWO_WAY_LANE;
316
317 String carFollowingModelName = null;
318 CompoundProperty propertyContainer = new CompoundProperty("", "", "", this.properties, false, 0);
319 Property<?> cfmp = propertyContainer.findByKey("CarFollowingModel");
320 if (null == cfmp)
321 {
322 throw new Error("Cannot find \"Car following model\" property");
323 }
324 if (cfmp instanceof SelectionProperty)
325 {
326 carFollowingModelName = ((SelectionProperty) cfmp).getValue();
327 }
328 else
329 {
330 throw new Error("\"Car following model\" property has wrong type");
331 }
332
333
334 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
335 {
336 if (ap instanceof CompoundProperty)
337 {
338 cp = (CompoundProperty) ap;
339 if (ap.getKey().contains("IDM"))
340 {
341
342 Acceleration a = IDMPropertySet.getA(cp);
343 Acceleration b = IDMPropertySet.getB(cp);
344 Length s0 = IDMPropertySet.getS0(cp);
345 Duration tSafe = IDMPropertySet.getTSafe(cp);
346 GTUFollowingModelOld gtuFollowingModel = null;
347 if (carFollowingModelName.equals("IDM"))
348 {
349 gtuFollowingModel = new IDMOld(a, b, s0, tSafe, 1.0);
350 }
351 else if (carFollowingModelName.equals("IDM+"))
352 {
353 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
354 }
355 else
356 {
357 throw new Error("Unknown gtu following model: " + carFollowingModelName);
358 }
359 if (ap.getKey().contains("Car"))
360 {
361 this.carFollowingModelCars = gtuFollowingModel;
362 }
363 else if (ap.getKey().contains("Truck"))
364 {
365 this.carFollowingModelTrucks = gtuFollowingModel;
366 }
367 else
368 {
369 throw new Error("Cannot determine gtu type for " + ap.getKey());
370 }
371 }
372 }
373 }
374
375
376 cfmp = propertyContainer.findByKey("LaneChanging");
377 if (null == cfmp)
378 {
379 throw new Error("Cannot find \"Lane changing\" property");
380 }
381 if (cfmp instanceof SelectionProperty)
382 {
383 String laneChangeModelName = ((SelectionProperty) cfmp).getValue();
384 if ("Egoistic".equals(laneChangeModelName))
385 {
386 this.laneChangeModel = new Egoistic();
387 }
388 else if ("Altruistic".equals(laneChangeModelName))
389 {
390 this.laneChangeModel = new Altruistic();
391 }
392 else
393 {
394 throw new Error("Lane changing " + laneChangeModelName + " not implemented");
395 }
396 }
397 else
398 {
399 throw new Error("\"Lane changing\" property has wrong type");
400 }
401
402 StringBuilder xmlCode = new StringBuilder();
403 xmlCode.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE xml>\n");
404 xmlCode.append("<NETWORK xmlns=\"http://www.opentrafficsim.org/ots\" "
405 + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
406 xmlCode.append("\txsi:schemaLocation=\"http://www.opentrafficsim.org/ots "
407 + "http://www.opentrafficsim.org/docs/current/ots-network.xsd\">\n\n");
408 xmlCode.append("\t<DEFINITIONS>\n\n");
409 xmlCode.append("\t<GLOBAL />\n\n");
410 xmlCode.append("\t\t<GTUTYPE NAME=\"CAR\" />\n");
411 xmlCode.append("\t\t<GTUTYPE NAME=\"TRUCK\" />\n\n");
412 xmlCode.append("\t\t<GTU NAME=\"CAR\" GTUTYPE=\"CAR\" LENGTH=\"UNIF(4,7) m\" WIDTH=\"UNIF(1.7, 2) m\" "
413 + "MAXSPEED=\"CONST(120) km/h\" />\n");
414 xmlCode.append("\t\t<GTU NAME=\"TRUCK\" GTUTYPE=\"TRUCK\" LENGTH=\"UNIF(16,24) m\" WIDTH=\"UNIF(2.2, 2.7) m\" "
415 + "MAXSPEED=\"CONST(100) km/h\" />\n\n");
416 xmlCode.append("\t\t<GTUMIX NAME=\"gtumix\">\n");
417 xmlCode.append("\t\t\t<GTU NAME=\"CAR\" WEIGHT=\"" + (100 * this.carProbability) + "\"></GTU>\n");
418 xmlCode.append("\t\t\t<GTU NAME=\"TRUCK\" WEIGHT=\"" + (100 - 100 * this.carProbability) + "\"></GTU>\n");
419 xmlCode.append("\t\t</GTUMIX>\n\n");
420
421 xmlCode.append("\t\t<ROADTYPE NAME=\"NORMALROAD\" DEFAULTLANEWIDTH=\"3.5m\" DEFAULTLANEKEEPING=\"KEEPRIGHT\"\n"
422 + "\t\t\tDEFAULTOVERTAKING=\"LEFTSET([CAR, TRUCK] OVERTAKE [ALL]) RIGHTSPEED(40 km/h)\">\n");
423 xmlCode.append("\t\t\t<SPEEDLIMIT GTUTYPE=\"CAR\" LEGALSPEEDLIMIT=\"60km/h\" />\n");
424 xmlCode.append("\t\t</ROADTYPE>\n");
425
426 xmlCode.append(makeRoadLayout("BRANCH", lanesOnBranch));
427 xmlCode.append(makeRoadLayout("MAIN", lanesOnMain));
428 xmlCode.append(makeRoadLayout("COMMON", lanesOnCommon));
429 xmlCode.append(makeRoadLayout("COMMONCOMPRESSED", lanesOnCommonCompressed));
430
431 xmlCode.append("\t</DEFINITIONS>\n");
432 xmlCode.append("\t<NODE NAME=\"From\" COORDINATE=\"(0,0,0)\" ANGLE=\"0 deg\" />\n");
433 xmlCode.append("\t<NODE NAME=\"End\" COORDINATE=\"(2000,0,0)\" ANGLE=\"0 deg\" />\n");
434 xmlCode.append("\t<NODE NAME=\"From2\" COORDINATE=\"(0,-50,0)\" ANGLE=\"0 deg\" />\n");
435 xmlCode.append("\t<NODE NAME=\"FirstVia\" COORDINATE=\"(500,0,0)\" ANGLE=\"0 deg\" />\n");
436 xmlCode.append("\t<NODE NAME=\"SecondVia\" COORDINATE=\"(1000,0,0)\" ANGLE=\"0 deg\" />\n");
437 xmlCode.append("\t<NODE NAME=\"End2\" COORDINATE=\"(2000,-50,0)\" ANGLE=\"0 deg\" />\n");
438
439
440
441
442
443
444
445
446
447 if (merge)
448 {
449
450 xmlCode.append("\t<ROUTE NAME=\"ALL\" NODELIST=\"FirstVia SecondVia End\" />");
451 xmlCode.append("\t<ROUTEMIX NAME=\"routemix\" >\n");
452 xmlCode.append("\t\t<ROUTE WEIGHT=\"1\" NAME=\"ALL\" />\n");
453 xmlCode.append("\t</ROUTEMIX>\n");
454
455
456
457
458
459
460 }
461 else
462 {
463
464 xmlCode.append("\t<ROUTE NAME=\"From_End\" NODELIST=\"FirstVia SecondVia End\" />\n");
465 xmlCode.append("\t<ROUTE NAME=\"From_End2\" NODELIST=\"FirstVia SecondVia End2\" />\n");
466 xmlCode.append("\t<ROUTEMIX NAME=\"routemix\" >\n");
467 xmlCode.append("\t\t<ROUTE WEIGHT=\"" + lanesOnMain + "\" NAME=\"toEnd\" />\n");
468 xmlCode.append("\t\t<ROUTE WEIGHT=\"" + lanesOnBranch + "\" NAME=\"toEnd2\" />\n");
469 xmlCode.append("\t</ROUTEMIX>\n");
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495 }
496
497
498 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
499 {
500 if (ap instanceof SelectionProperty)
501 {
502 SelectionProperty sp = (SelectionProperty) ap;
503 if ("TacticalPlanner".equals(sp.getKey()))
504 {
505 String tacticalPlannerName = sp.getValue();
506 if ("IDM".equals(tacticalPlannerName))
507 {
508 new LaneBasedStrategicalRoutePlannerFactory(
509 new LaneBasedGTUFollowingTacticalPlannerFactory(this.carFollowingModelCars));
510 new LaneBasedStrategicalRoutePlannerFactory(
511 new LaneBasedGTUFollowingTacticalPlannerFactory(this.carFollowingModelTrucks));
512 }
513 else if ("MOBIL/IDM".equals(tacticalPlannerName))
514 {
515 new LaneBasedStrategicalRoutePlannerFactory(
516 new LaneBasedCFLCTacticalPlannerFactory(this.carFollowingModelCars, this.laneChangeModel));
517 new LaneBasedStrategicalRoutePlannerFactory(new LaneBasedCFLCTacticalPlannerFactory(
518 this.carFollowingModelTrucks, this.laneChangeModel));
519 }
520 else if ("DIRECTED/IDM".equals(tacticalPlannerName))
521 {
522 new LaneBasedStrategicalRoutePlannerFactory(
523 new LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory(this.carFollowingModelCars));
524 new LaneBasedStrategicalRoutePlannerFactory(
525 new LaneBasedGTUFollowingDirectedChangeTacticalPlannerFactory(
526 this.carFollowingModelTrucks));
527 }
528 else if ("LMRS".equals(tacticalPlannerName))
529 {
530
531 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
532 new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
533 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
534 new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
535 }
536 else if ("Toledo".equals(tacticalPlannerName))
537 {
538 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
539 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
540 }
541 else
542 {
543 throw new Error("Don't know how to create a " + tacticalPlannerName + " tactical planner");
544 }
545 }
546
547 }
548 else if (ap instanceof ProbabilityDistributionProperty)
549 {
550 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) ap;
551 String modelName = ap.getKey();
552 if (modelName.equals("TrafficComposition"))
553 {
554 this.carProbability = pdp.getValue()[0];
555 }
556 }
557 else if (ap instanceof ContinuousProperty)
558 {
559 ContinuousProperty contP = (ContinuousProperty) ap;
560 if (contP.getKey().startsWith("Flow"))
561 {
562 this.averageHeadway = new Duration(3600.0 / contP.getValue(), SECOND);
563 this.minimumHeadway = new Duration(3, SECOND);
564 this.headwayGenerator = new DistErlang(new MersenneTwister(1234), 4,
565 DoubleScalar.minus(this.averageHeadway, this.minimumHeadway).getSI());
566 }
567 }
568 else if (ap instanceof CompoundProperty)
569 {
570 CompoundProperty compoundProperty = (CompoundProperty) ap;
571 if (ap.getKey().equals("Output"))
572 {
573 continue;
574 }
575 if (ap.getKey().contains("IDM"))
576 {
577 Acceleration a = IDMPropertySet.getA(compoundProperty);
578 Acceleration b = IDMPropertySet.getB(compoundProperty);
579 Length s0 = IDMPropertySet.getS0(compoundProperty);
580 Duration tSafe = IDMPropertySet.getTSafe(compoundProperty);
581 GTUFollowingModelOld gtuFollowingModel = null;
582 if (carFollowingModelName.equals("IDM"))
583 {
584 gtuFollowingModel = new IDMOld(a, b, s0, tSafe, 1.0);
585 }
586 else if (carFollowingModelName.equals("IDM+"))
587 {
588 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
589 }
590 else
591 {
592 throw new Error("Unknown gtu following model: " + carFollowingModelName);
593 }
594 if (ap.getKey().contains("Car"))
595 {
596 this.carFollowingModelCars = gtuFollowingModel;
597 }
598 else if (ap.getKey().contains("Truck"))
599 {
600 this.carFollowingModelTrucks = gtuFollowingModel;
601 }
602 else
603 {
604 throw new Error("Cannot determine gtu type for " + ap.getKey());
605 }
606 }
607 }
608 }
609
610 if (merge)
611 {
612 xmlCode.append("\t<LINK NAME=\"From2 to FirstVia\" NODESTART=\"From2\" NODEEND=\"FirstVia\" "
613 + "ROADLAYOUT=\"BRANCH\">\n");
614 xmlCode.append("\t\t<STRAIGHT />\n");
615 for (int lane = 1; lane <= lanesOnBranch; lane++)
616 {
617 xmlCode.append("\t\t<GENERATOR LANE=\"Lane" + lane + "\" POSITION=\"16m\" IAT=\"ERLANG(4,"
618 + this.averageHeadway.minus(this.minimumHeadway).si + ") s\" "
619 + "INITIALSPEED=\"UNIFORM(80,90) km/h\" GTUMIX=\"gtumix\" ROUTEMIX=\"routemix\"\n"
620 + "\t\t\tGTUCOLORER=\"SWITCHABLE\" />\n");
621
622 }
623 xmlCode.append("\t</LINK>\n");
624 }
625 else
626 {
627 xmlCode.append("\t<LINK NAME=\"SecondVia to End2\" NODESTART=\"SecondVia\" NODEEND=\"End2\" "
628 + "ROADLAYOUT=\"BRANCH\">\n");
629 xmlCode.append("\t\t<STRAIGHT />\n");
630
631 for (int lane = 1; lane <= lanesOnBranch; lane++)
632 {
633 xmlCode.append("\t\t<SINK POSITION=\"999m\" LANE=\"Lane" + lane + "\" />\n");
634 }
635 xmlCode.append("\t</LINK>\n");
636
637
638
639
640
641
642 }
643 xmlCode.append(
644 "\t<LINK NAME=\"From to FirstVia\" NODESTART=\"From2\" NODEEND=\"FirstVia\" " + "ROADLAYOUT=\"MAIN\">\n");
645 xmlCode.append("\t\t<STRAIGHT />\n");
646 for (int lane = 1; lane <= (merge ? lanesOnMain : lanesOnCommonCompressed); lane++)
647 {
648 xmlCode.append("\t\t<GENERATOR LANE=\"Lane" + lane + "\" POSITION=\"16m\" IAT=\"ERLANG(4,"
649 + this.averageHeadway.minus(this.minimumHeadway).si + ") s\" "
650 + "INITIALSPEED=\"UNIFORM(80,90) km/h\" GTUMIX=\"gtumix\" ROUTEMIX=\"routemix\"\n"
651 + "\t\t\tGTUCOLORER=\"SWITCHABLE\" />\n");
652
653 }
654 xmlCode.append("\t</LINK>\n");
655
656
657
658
659
660
661
662 xmlCode.append("\t<LINK NAME=\"FirstVia to SecondVia\" NODESTART=\"FirstVia\" NODEEND=\"SecondVia\" "
663 + "ROADLAYOUT=\"COMMON\">\n");
664 xmlCode.append("\t\t<STRAIGHT />\n");
665 for (int lane = lanesOnCommonCompressed + 1; lane <= lanesOnCommon; lane++)
666 {
667 xmlCode.append("\t\t<BLOCK LANE=\"Lane" + lane + "\" POSITION=\"END-1mm\" />\n");
668 }
669 xmlCode.append("\t</LINK>\n");
670
671
672
673
674
675
676
677
678
679 xmlCode.append("\t<LINK NAME=\"SecondVia to End2\" NODESTART=\"SecondVia\" NODEEND=\"End2\" "
680 + "ROADLAYOUT=\"BRANCH\">\n");
681 xmlCode.append("\t\t<STRAIGHT />\n");
682
683 for (int lane = 1; lane <= lanesOnBranch; lane++)
684 {
685 xmlCode.append("\t\t<SINK POSITION=\"999m\" LANE=\"Lane" + lane + "\" />\n");
686 }
687 xmlCode.append("\t</LINK>\n");
688
689
690 xmlCode.append(
691 "\t<LINK NAME=\"SecondVia to End\" NODESTART=\"SecondVia\" NODEEND=\"End\" " + "ROADLAYOUT=\"BRANCH\">");
692 xmlCode.append("\t\t<STRAIGHT />\n");
693
694 for (int lane = 1; lane <= lanesOnBranch; lane++)
695 {
696 xmlCode.append("\t\t<SINK POSITION=\"999m\" LANE=\"Lane" + lane + "\" />\n");
697 }
698 xmlCode.append("\t</LINK>\n");
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732 xmlCode.append("</NETWORK>\n");
733 XmlNetworkLaneParser nlp = new XmlNetworkLaneParser((DEVSSimulatorInterface.TimeDoubleUnit) theSimulator);
734
735 System.out.println("Building network from XML description\n" + xmlCode.toString());
736 nlp.build(new ByteArrayInputStream(xmlCode.toString().getBytes()), this.network, true);
737 this.simulator.scheduleEventAbs(new Time(0.999, TimeUnit.BASE_SECOND), this, this, "drawGraphs", null);
738 }
739 catch (NamingException | NetworkException | GTUException | OTSGeometryException | PropertyException
740 | ParserConfigurationException | SAXException | IOException | ValueException | ParameterException exception1)
741 {
742 exception1.printStackTrace();
743 }
744 }
745
746
747 static final double LANE_WIDTH = 3.5;
748
749
750
751
752
753
754 private String makeRoadLayout(final String name, final int lanes)
755 {
756 StringBuilder xmlCode = new StringBuilder();
757 xmlCode.append("\t\t<ROADLAYOUT NAME=\"" + name + "\" ROADTYPE=\"NORMALROAD\">\n");
758 xmlCode.append("\t\t\t<SHOULDER WIDTH=\"2m\" OFFSET=\"-1m\" COLOR=\"GREEN\" />\n");
759 double cumulativeOffset = 0;
760 for (int lane = 0; lane < lanes; lane++)
761 {
762 xmlCode.append("\t\t\t<STRIPE TYPE=\"" + (0 == lane ? "SOLID" : "DASHED") + "\" OFFSET=\"1m\" WIDTH=\"20cm\" />\n");
763 xmlCode.append("\t\t\t<LANE NAME=\"Lane" + (lane + 1) + "\" OFFSET=\"" + (cumulativeOffset + LANE_WIDTH / 2)
764 + "m\" DIRECTION=\"FORWARD\" />\n");
765 cumulativeOffset += LANE_WIDTH;
766 }
767 xmlCode.append("\t\t\t<STRIPE TYPE=\"SOLID\" OFFSET=\"" + cumulativeOffset + "m\" WIDTH=\"20cm\" />\n");
768 xmlCode.append("\t\t\t<SHOULDER WIDTH=\"2m\" OFFSET=\"" + (cumulativeOffset + 1) + "m\" COLOR=\"GREEN\" />\n");
769 xmlCode.append("\t\t</ROADLAYOUT>\n");
770 return xmlCode.toString();
771 }
772
773
774
775
776
777
778
779
780
781
782
783
784 LaneBasedTemplateGTUType makeTemplate(final StreamInterface stream, final Lane lane,
785 final ContinuousDistDoubleScalar.Rel<Length, LengthUnit> lengthDistribution,
786 final ContinuousDistDoubleScalar.Rel<Length, LengthUnit> widthDistribution,
787 final ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> maximumSpeedDistribution,
788 final Set<DirectedLanePosition> initialPositions,
789 final LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerFactory) throws GTUException
790 {
791 return new LaneBasedTemplateGTUType(this.gtuType, new Generator<Length>()
792 {
793 @Override
794 public Length draw()
795 {
796 return lengthDistribution.draw();
797 }
798 }, new Generator<Length>()
799 {
800 @Override
801 public Length draw()
802 {
803 return widthDistribution.draw();
804 }
805 }, new Generator<Speed>()
806 {
807 @Override
808 public Speed draw()
809 {
810 return maximumSpeedDistribution.draw();
811 }
812 },
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830 strategicalPlannerFactory, this.routeGenerator);
831
832 }
833
834
835
836
837 protected final void drawGraphs()
838 {
839 for (LaneBasedGTUSampler plot : this.plots)
840 {
841 plot.reGraph();
842 }
843
844 try
845 {
846 this.simulator.scheduleEventAbs(new Time(this.simulator.getSimulatorTime().getSI() + 1, TimeUnit.BASE_SECOND),
847 this, this, "drawGraphs", null);
848 }
849 catch (SimRuntimeException exception)
850 {
851 exception.printStackTrace();
852 }
853
854 }
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934 @Override
935 public SimulatorInterface<Time, Duration, SimTimeDoubleUnit> getSimulator()
936 {
937 return this.simulator;
938 }
939
940
941 @Override
942 public OTSNetwork getNetwork()
943 {
944 return this.network;
945 }
946
947
948
949
950
951
952
953
954
955
956
957
958
959 private class DirectionGTUColorer implements GTUColorer
960 {
961
962 private List<LegendEntry> legend = new ArrayList<>();
963
964
965 DirectionGTUColorer()
966 {
967 super();
968 this.legend.add(new LegendEntry(Color.RED, "Right", "Go right"));
969 this.legend.add(new LegendEntry(Color.BLUE, "Main", "Main route"));
970 }
971
972
973 @Override
974 public Color getColor(final GTU gtu)
975 {
976 AbstractLaneBasedGTU laneBasedGTU = (AbstractLaneBasedGTU) gtu;
977 Route route = ((LaneBasedStrategicalRoutePlanner) laneBasedGTU.getStrategicalPlanner()).getRoute();
978 if (route == null)
979 {
980 return Color.black;
981 }
982 if (route.toString().toLowerCase().contains("end2"))
983 {
984 return Color.red;
985 }
986 if (route.toString().toLowerCase().contains("end"))
987 {
988 return Color.blue;
989 }
990 return Color.black;
991 }
992
993
994 @Override
995 public List<LegendEntry> getLegend()
996 {
997 return this.legend;
998 }
999 }
1000
1001 }