1 package org.opentrafficsim.imb.demo;
2
3 import java.awt.Color;
4 import java.awt.Dimension;
5 import java.awt.geom.Rectangle2D;
6 import java.lang.reflect.InvocationTargetException;
7 import java.rmi.RemoteException;
8 import java.util.ArrayList;
9 import java.util.HashSet;
10 import java.util.LinkedHashSet;
11 import java.util.List;
12 import java.util.Random;
13 import java.util.Set;
14
15 import javax.naming.NamingException;
16 import javax.swing.JFrame;
17 import javax.swing.SwingUtilities;
18
19 import org.djunits.unit.LengthUnit;
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.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.BooleanProperty;
28 import org.opentrafficsim.base.modelproperties.CompoundProperty;
29 import org.opentrafficsim.base.modelproperties.ContinuousProperty;
30 import org.opentrafficsim.base.modelproperties.IntegerProperty;
31 import org.opentrafficsim.base.modelproperties.ProbabilityDistributionProperty;
32 import org.opentrafficsim.base.modelproperties.Property;
33 import org.opentrafficsim.base.modelproperties.PropertyException;
34 import org.opentrafficsim.base.modelproperties.SelectionProperty;
35 import org.opentrafficsim.core.dsol.OTSDEVSRealTimeClock;
36 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
37 import org.opentrafficsim.core.dsol.OTSModelInterface;
38 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
39 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
40 import org.opentrafficsim.core.geometry.OTSGeometryException;
41 import org.opentrafficsim.core.geometry.OTSPoint3D;
42 import org.opentrafficsim.core.gtu.GTUDirectionality;
43 import org.opentrafficsim.core.gtu.GTUException;
44 import org.opentrafficsim.core.gtu.GTUType;
45 import org.opentrafficsim.core.gtu.RelativePosition;
46 import org.opentrafficsim.core.gtu.animation.DefaultSwitchableGTUColorer;
47 import org.opentrafficsim.core.gtu.animation.GTUColorer;
48 import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
49 import org.opentrafficsim.core.network.LongitudinalDirectionality;
50 import org.opentrafficsim.core.network.Network;
51 import org.opentrafficsim.core.network.NetworkException;
52 import org.opentrafficsim.core.network.OTSNetwork;
53 import org.opentrafficsim.core.network.OTSNode;
54 import org.opentrafficsim.graphs.LaneBasedGTUSampler;
55 import org.opentrafficsim.imb.IMBException;
56 import org.opentrafficsim.imb.connector.IMBConnector;
57 import org.opentrafficsim.imb.transceiver.urbanstrategy.GTUTransceiver;
58 import org.opentrafficsim.imb.transceiver.urbanstrategy.LaneGTUTransceiver;
59 import org.opentrafficsim.imb.transceiver.urbanstrategy.LinkGTUTransceiver;
60 import org.opentrafficsim.imb.transceiver.urbanstrategy.NetworkTransceiver;
61 import org.opentrafficsim.imb.transceiver.urbanstrategy.NodeTransceiver;
62 import org.opentrafficsim.imb.transceiver.urbanstrategy.SensorGTUTransceiver;
63 import org.opentrafficsim.imb.transceiver.urbanstrategy.SimulatorTransceiver;
64 import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation;
65 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
66 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
67 import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlannerFactory;
68 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
69 import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld;
70 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMOld;
71 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
72 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld;
73 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.AbstractLaneChangeModel;
74 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Altruistic;
75 import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic;
76 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
77 import org.opentrafficsim.road.gtu.lane.tactical.toledo.ToledoFactory;
78 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
79 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
80 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
81 import org.opentrafficsim.road.modelproperties.IDMPropertySet;
82 import org.opentrafficsim.road.network.factory.LaneFactory;
83 import org.opentrafficsim.road.network.lane.CrossSectionElement;
84 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
85 import org.opentrafficsim.road.network.lane.Lane;
86 import org.opentrafficsim.road.network.lane.LaneType;
87 import org.opentrafficsim.road.network.lane.object.LaneBasedObject;
88 import org.opentrafficsim.road.network.lane.object.sensor.AbstractSensor;
89 import org.opentrafficsim.road.network.lane.object.sensor.SensorAnimation;
90
91 import nl.tno.imb.TConnection;
92 import nl.tno.imb.mc.ModelParameters;
93 import nl.tno.imb.mc.ModelStarter;
94 import nl.tno.imb.mc.ModelState;
95 import nl.tno.imb.mc.Parameter;
96 import nl.tudelft.simulation.dsol.SimRuntimeException;
97 import nl.tudelft.simulation.dsol.animation.D2.AnimationPanel;
98 import nl.tudelft.simulation.dsol.experiment.Replication;
99 import nl.tudelft.simulation.dsol.experiment.ReplicationMode;
100 import nl.tudelft.simulation.dsol.simulators.AnimatorInterface;
101 import nl.tudelft.simulation.dsol.simulators.Simulator;
102 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
103 import nl.tudelft.simulation.event.Event;
104
105
106
107
108
109
110
111
112
113
114
115
116 public class ModelControlDemo extends ModelStarter
117 {
118
119 private CircularRoadIMB model = null;
120
121
122
123
124
125
126
127 public ModelControlDemo(String[] args, String providedModelName, int providedModelId) throws IMBException
128 {
129 super(args, providedModelName, providedModelId);
130 }
131
132
133
134
135
136
137
138
139 private Property<?> findPropertyInList(final List<Property<?>> properties, final String key)
140 {
141 for (Property<?> property : properties)
142 {
143 for (Property<?> p : property)
144 {
145 String keyPath = p.getKey();
146 for (Property<?> parent = p.getParent(); null != parent; parent = parent.getParent())
147 {
148 keyPath = parent.getKey() + "." + keyPath;
149 }
150
151 if (key.equals(keyPath))
152 {
153 return property;
154 }
155 }
156 }
157 return null;
158 }
159
160
161 @Override
162 public void startModel(final ModelParameters parameters, final TConnection tConnection)
163 {
164 System.out.println("startModel called");
165 System.out.println("parameters: " + parameters);
166 System.out.println("Connection: " + this.connection);
167 String dataSource = null;
168 List<Property<?>> properties = CircularRoadIMB.getSupportedProperties();
169
170 for (String parameterName : parameters.getParameterNames())
171 {
172 if (parameterName.equals("Federation"))
173 {
174 continue;
175 }
176 else if (parameterName.equals("DataSource"))
177 {
178 dataSource = (String) parameters.getParameterByName(parameterName).getValue();
179 continue;
180 }
181 int pos = parameterName.indexOf(" (");
182 if (pos < 0)
183 {
184 System.out.println("ignoring parameter " + parameterName);
185 continue;
186 }
187 String strippedName = parameterName.substring(0, pos);
188 switch (strippedName)
189 {
190 case "Truck fraction":
191 {
192 Property<?> p = findPropertyInList(properties, "TrafficComposition");
193 if (null == p || !(p instanceof ProbabilityDistributionProperty))
194 {
195 System.err.println("Property " + p + " is not a ProbalityDistributionProperty");
196 }
197 else
198 {
199 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) p;
200 Double[] values = pdp.getValue();
201 values[1] = (double) parameters.getParameterByName(parameterName).getValue();
202 values[0] = 1.0 - values[1];
203 try
204 {
205 System.out.println("Setting TrafficComposition to " + values);
206 pdp.setValue(values);
207 }
208 catch (PropertyException exception)
209 {
210 exception.printStackTrace();
211 }
212 }
213 break;
214 }
215 default:
216 System.out.println("Ignoring parameter " + parameterName);
217 break;
218 }
219 }
220 System.out.println("Not doing anything with dataSource " + dataSource);
221
222 try
223 {
224 IMBConnector simulationIMBConnector = new IMBConnector(this.connection);
225 System.out.println("IMBConnector for simulation is " + simulationIMBConnector);
226 this.model = new CircularRoadIMB(new DefaultSwitchableGTUColorer(), new OTSNetwork(""), properties,
227 simulationIMBConnector);
228 Replication<Time, Duration, OTSSimTimeDouble> replication = new Replication<Time, Duration, OTSSimTimeDouble>(
229 "rep1", new OTSSimTimeDouble(Time.ZERO), Duration.ZERO, new Duration(1, TimeUnit.HOUR), this.model);
230 OTSDEVSRealTimeClock simulator = new OTSDEVSRealTimeClock();
231 simulator.initialize(replication, ReplicationMode.TERMINATING);
232 signalModelState(ModelState.READY);
233 System.out.println("Reported ModelState.READY");
234 }
235 catch (PropertyException | IMBException | SimRuntimeException | NamingException exception)
236 {
237 exception.printStackTrace();
238 }
239 }
240
241
242 @Override
243 public void stopModel()
244 {
245 System.out.println("stopModel called");
246 if (null != this.model)
247 {
248 try
249 {
250 ((Simulator<Time, Duration, OTSSimTimeDouble>) this.model.getSimulator()).cleanUp();
251 this.model.closeWindow();
252 this.model = null;
253 }
254 catch (RemoteException exception)
255 {
256 exception.printStackTrace();
257 }
258 }
259 else
260 {
261 System.err.println("stopModel called, but no model is running");
262 }
263 }
264
265
266 @Override
267 public void quitApplication()
268 {
269 if (null != this.model)
270 {
271 try
272 {
273
274 ((Simulator<Time, Duration, OTSSimTimeDouble>) this.model.getSimulator()).cleanUp();
275 }
276 catch (Exception exception)
277 {
278 System.out.println("caught Exception in quitApplication:");
279 exception.printStackTrace();
280 }
281 }
282 System.out.println("quitApplication called");
283 }
284
285
286 @Override
287 public void parameterRequest(ModelParameters parameters)
288 {
289 System.out.println("serving parameter request");
290 System.out.println("received parameters: " + parameters);
291 List<Property<?>> propertyList = CircularRoadIMB.getSupportedProperties();
292 Property<?> truckFraction = findByKeyInList(propertyList, "TrafficComposition");
293 if (null != truckFraction)
294 {
295 parameters.addParameter(new Parameter("Truck fraction (range 0.0 - 1.0)",
296 ((ProbabilityDistributionProperty) truckFraction).getValue()[1]));
297 }
298 System.out.println("(possibly) modified paramters: " + parameters);
299 }
300
301
302
303
304
305
306
307 private Property<?> findByKeyInList(final List<Property<?>> propertyList, final String key)
308 {
309 Property<?> result = null;
310 for (Property<?> property : propertyList)
311 {
312 Property<?> p = property.findByKey(key);
313 if (null != p)
314 {
315 if (null != result)
316 {
317 System.err.println("Duplicate property with key " + key + " in provided list");
318 }
319 result = p;
320 }
321 }
322 return result;
323 }
324
325
326
327
328
329
330
331 public static void main(final String[] args) throws InvocationTargetException, InterruptedException
332 {
333 SwingUtilities.invokeAndWait(new Runnable()
334 {
335
336 @Override
337 public void run()
338 {
339 try
340 {
341 new ModelControlDemo(args, "Demo Model", 1234);
342 }
343 catch (IMBException exception)
344 {
345 exception.printStackTrace();
346 }
347 }
348 });
349 }
350
351
352
353
354
355
356
357
358
359
360
361
362 static class CircularRoadIMB implements OTSModelInterface, UNITS
363 {
364
365 private static final long serialVersionUID = 20141121L;
366
367
368 private OTSDEVSSimulatorInterface simulator;
369
370
371 private int carsCreated = 0;
372
373
374 private GTUFollowingModelOld carFollowingModelCars;
375
376
377 private GTUFollowingModelOld carFollowingModelTrucks;
378
379
380 private double carProbability;
381
382
383 private AbstractLaneChangeModel laneChangeModel;
384
385
386 private Length minimumDistance = new Length(0, METER);
387
388
389 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
390
391
392 private List<LaneBasedGTUSampler> plots = new ArrayList<LaneBasedGTUSampler>();
393
394
395 private final List<Property<?>> properties;
396
397
398 private List<List<Lane>> paths = new ArrayList<>();
399
400
401 private Random randomGenerator = new Random(12345);
402
403
404 private final GTUColorer gtuColorer;
405
406
407 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
408
409
410 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
411
412
413 private final OTSNetwork network;
414
415
416 private final IMBConnector imbConnector;
417
418
419 private JFrame frame;
420
421
422
423
424
425
426
427
428 CircularRoadIMB(final GTUColorer gtuColorer, final OTSNetwork network, final List<Property<?>> properties,
429 final IMBConnector imbConnector) throws PropertyException
430 {
431 this.properties = properties;
432 this.gtuColorer = gtuColorer;
433 this.network = network;
434 this.imbConnector = imbConnector;
435 }
436
437
438
439
440
441 public static List<Property<?>> getSupportedProperties()
442 {
443 List<Property<?>> result = new ArrayList<>();
444 result.add(new SelectionProperty("LaneChanging", "Lane changing",
445 "<html>The lane change strategies vary in politeness.<br>"
446 + "Two types are implemented:<ul><li>Egoistic (looks only at personal gain).</li>"
447 + "<li>Altruistic (assigns effect on new and current follower the same weight as "
448 + "the personal gain).</html>",
449 new String[] { "Egoistic", "Altruistic" }, 0, false, 500));
450 result.add(new SelectionProperty("TacticalPlanner", "Tactical planner",
451 "<html>The tactical planner determines if a lane change is desired and possible.</html>",
452 new String[] { "MOBIL", "LMRS", "Toledo" }, 0, false, 600));
453 result.add(new IntegerProperty("TrackLength", "Track length", "Circumference of the track", 2000, 500, 6000,
454 "Track length %dm", false, 10));
455 result.add(new ContinuousProperty("MeanDensity", "Mean density", "Number of vehicles per km", 40.0, 5.0, 45.0,
456 "Density %.1f veh/km", false, 11));
457 result.add(new ContinuousProperty("DensityVariability", "Density variability",
458 "Variability of the number of vehicles per km", 0.0, 0.0, 1.0, "%.1f", false, 12));
459 List<Property<?>> outputProperties = new ArrayList<>();
460 try
461 {
462 for (int lane = 1; lane <= 2; lane++)
463 {
464 String laneId = String.format("Lane %d ", lane);
465 outputProperties.add(new BooleanProperty(laneId + "Density", laneId + " Density",
466 laneId + "Density contour plot", true, false, 0));
467 outputProperties.add(new BooleanProperty(laneId + "Flow", laneId + " Flow", laneId + "Flow contour plot",
468 true, false, 1));
469 outputProperties.add(new BooleanProperty(laneId + "Speed", laneId + " Speed", laneId + "Speed contour plot",
470 true, false, 2));
471 outputProperties.add(new BooleanProperty(laneId + "Acceleration", laneId + " Acceleration",
472 laneId + "Acceleration contour plot", true, false, 3));
473 outputProperties.add(new BooleanProperty(laneId + "Trajectories", laneId + " Trajectories",
474 laneId + "Trajectory (time/distance) diagram", true, false, 4));
475 }
476 result.add(new CompoundProperty("OutputGraphs", "Output graphs", "Select the graphical output",
477 outputProperties, true, 1000));
478 result.add(new ProbabilityDistributionProperty("TrafficComposition", "Traffic composition",
479 "<html>Mix of passenger cars and trucks</html>", new String[] { "passenger car", "truck" },
480 new Double[] { 0.8, 0.2 }, false, 10));
481 result.add(new SelectionProperty("CarFollowingModel", "Car following model",
482 "<html>The car following model determines "
483 + "the acceleration that a vehicle will make taking into account "
484 + "nearby vehicles, infrastructural restrictions (e.g. speed limit, "
485 + "curvature of the road) capabilities of the vehicle and personality "
486 + "of the driver.</html>",
487 new String[] { "IDM", "IDM+" }, 1, false, 1));
488 result.add(IDMPropertySet.makeIDMPropertySet("IDMCar", "Car", new Acceleration(1.0, METER_PER_SECOND_2),
489 new Acceleration(1.5, METER_PER_SECOND_2), new Length(2.0, METER), new Duration(1.0, SECOND), 2));
490 result.add(IDMPropertySet.makeIDMPropertySet("IDMTruck", "Truck", new Acceleration(0.5, METER_PER_SECOND_2),
491 new Acceleration(1.25, METER_PER_SECOND_2), new Length(2.0, METER), new Duration(1.0, SECOND), 3));
492 }
493 catch (PropertyException exception)
494 {
495 exception.printStackTrace();
496 }
497 return result;
498 }
499
500
501
502
503
504 public Network getNetwork()
505 {
506 return this.network;
507 }
508
509
510
511
512
513 public List<Lane> getPath(final int index)
514 {
515 return this.paths.get(index);
516 }
517
518
519 @Override
520 public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
521 throws SimRuntimeException, RemoteException
522 {
523 AnimationPanel panel = null;
524 if (theSimulator instanceof AnimatorInterface)
525 {
526 this.frame = new JFrame("Circular Road Simulation with IMB Model Control");
527 panel = new AnimationPanel(new Rectangle2D.Double(-1000, -1000, 2000, 2000), new Dimension(1000, 1000),
528 theSimulator);
529 this.frame.add(panel);
530 this.frame.setSize(new Dimension(1000, 1000));
531 this.frame.setVisible(true);
532
533 panel.notify(new Event(SimulatorInterface.START_REPLICATION_EVENT, theSimulator, null));
534 }
535 OTSDEVSSimulatorInterface imbAnimator = (OTSDEVSSimulatorInterface) theSimulator;
536 if (null != this.imbConnector)
537 {
538 try
539 {
540 System.out.println("CirularRoadIMB: constructModel called; Connecting to IMB");
541 new NetworkTransceiver(this.imbConnector, imbAnimator, this.network);
542 new NodeTransceiver(this.imbConnector, imbAnimator, this.network);
543 new LinkGTUTransceiver(this.imbConnector, imbAnimator, this.network);
544 new LaneGTUTransceiver(this.imbConnector, imbAnimator, this.network);
545 new GTUTransceiver(this.imbConnector, imbAnimator, this.network);
546 new SensorGTUTransceiver(this.imbConnector, imbAnimator, this.network);
547 new SimulatorTransceiver(this.imbConnector, imbAnimator);
548 }
549 catch (IMBException exception)
550 {
551 throw new SimRuntimeException(exception);
552 }
553 }
554 final int laneCount = 2;
555 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
556 {
557 this.paths.add(new ArrayList<Lane>());
558 }
559 this.simulator = (OTSDEVSSimulatorInterface) theSimulator;
560 double radius = 6000 / 2 / Math.PI;
561 double headway = 40;
562 double headwayVariability = 0;
563 try
564 {
565
566 String carFollowingModelName = null;
567 CompoundProperty propertyContainer = new CompoundProperty("", "", "", this.properties, false, 0);
568 Property<?> cfmp = propertyContainer.findByKey("CarFollowingModel");
569 if (null == cfmp)
570 {
571 throw new Error("Cannot find \"Car following model\" property");
572 }
573 if (cfmp instanceof SelectionProperty)
574 {
575 carFollowingModelName = ((SelectionProperty) cfmp).getValue();
576 }
577 else
578 {
579 throw new Error("\"Car following model\" property has wrong type");
580 }
581
582
583 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
584 {
585 if (ap instanceof CompoundProperty)
586 {
587 CompoundProperty cp = (CompoundProperty) ap;
588
589 if (ap.getKey().contains("IDM"))
590 {
591 System.out.println("Car following model name appears to be " + ap.getKey());
592 Acceleration a = IDMPropertySet.getA(cp);
593 Acceleration b = IDMPropertySet.getB(cp);
594 Length s0 = IDMPropertySet.getS0(cp);
595 Duration tSafe = IDMPropertySet.getTSafe(cp);
596 GTUFollowingModelOld gtuFollowingModel = null;
597 if (carFollowingModelName.equals("IDM"))
598 {
599 gtuFollowingModel = new IDMOld(a, b, s0, tSafe, 1.0);
600 }
601 else if (carFollowingModelName.equals("IDM+"))
602 {
603 gtuFollowingModel = new IDMPlusOld(a, b, s0, tSafe, 1.0);
604 }
605 else
606 {
607 throw new Error("Unknown gtu following model: " + carFollowingModelName);
608 }
609 if (ap.getKey().contains("Car"))
610 {
611 this.carFollowingModelCars = gtuFollowingModel;
612 }
613 else if (ap.getKey().contains("Truck"))
614 {
615 this.carFollowingModelTrucks = gtuFollowingModel;
616 }
617 else
618 {
619 throw new Error("Cannot determine gtu type for " + ap.getKey());
620 }
621 }
622 }
623 }
624
625
626 cfmp = propertyContainer.findByKey("LaneChanging");
627 if (null == cfmp)
628 {
629 throw new Error("Cannot find \"Lane changing\" property");
630 }
631 if (cfmp instanceof SelectionProperty)
632 {
633 String laneChangeModelName = ((SelectionProperty) cfmp).getValue();
634 if ("Egoistic".equals(laneChangeModelName))
635 {
636 this.laneChangeModel = new Egoistic();
637 }
638 else if ("Altruistic".equals(laneChangeModelName))
639 {
640 this.laneChangeModel = new Altruistic();
641 }
642 else
643 {
644 throw new Error("Lane changing " + laneChangeModelName + " not implemented");
645 }
646 }
647 else
648 {
649 throw new Error("\"Lane changing\" property has wrong type");
650 }
651
652
653 for (Property<?> ap : new CompoundProperty("", "", "", this.properties, false, 0))
654 {
655 if (ap instanceof SelectionProperty)
656 {
657 SelectionProperty sp = (SelectionProperty) ap;
658 if ("TacticalPlanner".equals(sp.getKey()))
659 {
660 String tacticalPlannerName = sp.getValue();
661 if ("MOBIL".equals(tacticalPlannerName))
662 {
663 this.strategicalPlannerGeneratorCars =
664 new LaneBasedStrategicalRoutePlannerFactory(new LaneBasedCFLCTacticalPlannerFactory(
665 this.carFollowingModelCars, this.laneChangeModel));
666 this.strategicalPlannerGeneratorTrucks =
667 new LaneBasedStrategicalRoutePlannerFactory(new LaneBasedCFLCTacticalPlannerFactory(
668 this.carFollowingModelTrucks, this.laneChangeModel));
669 }
670 else if ("LMRS".equals(tacticalPlannerName))
671 {
672
673 BehavioralCharacteristics defaultBehavioralCFCharacteristics = new BehavioralCharacteristics();
674 defaultBehavioralCFCharacteristics.setDefaultParameters(AbstractIDM.class);
675 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
676 new LMRSFactory(new IDMPlusFactory(), defaultBehavioralCFCharacteristics));
677 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
678 new LMRSFactory(new IDMPlusFactory(), defaultBehavioralCFCharacteristics));
679 }
680 else if ("Toledo".equals(tacticalPlannerName))
681 {
682 this.strategicalPlannerGeneratorCars =
683 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
684 this.strategicalPlannerGeneratorTrucks =
685 new LaneBasedStrategicalRoutePlannerFactory(new ToledoFactory());
686 }
687 else
688 {
689 throw new Error("Don't know how to create a " + tacticalPlannerName + " tactical planner");
690 }
691 }
692 }
693 else if (ap instanceof ProbabilityDistributionProperty)
694 {
695 ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) ap;
696 if (ap.getKey().equals("TrafficComposition"))
697 {
698 this.carProbability = pdp.getValue()[0];
699 }
700 }
701 else if (ap instanceof IntegerProperty)
702 {
703 IntegerProperty ip = (IntegerProperty) ap;
704 if ("TrackLength".equals(ip.getKey()))
705 {
706 radius = ip.getValue() / 2 / Math.PI;
707 }
708 }
709 else if (ap instanceof ContinuousProperty)
710 {
711 ContinuousProperty cp = (ContinuousProperty) ap;
712 if (cp.getKey().equals("MeanDensity"))
713 {
714 headway = 1000 / cp.getValue();
715 }
716 if (cp.getKey().equals("DensityVariability"))
717 {
718 headwayVariability = cp.getValue();
719 }
720 }
721 else if (ap instanceof CompoundProperty)
722 {
723 if (ap.getKey().equals("OutputGraphs"))
724 {
725 continue;
726 }
727 }
728 }
729 GTUType gtuType = new GTUType("car");
730 Set<GTUType> compatibility = new HashSet<GTUType>();
731 compatibility.add(gtuType);
732 LaneType laneType = new LaneType("CarLane", compatibility);
733 OTSNode start = new OTSNode(this.network, "Start", new OTSPoint3D(radius, 0, 0));
734 OTSNode halfway = new OTSNode(this.network, "Halfway", new OTSPoint3D(-radius, 0, 0));
735
736 OTSPoint3D[] coordsHalf1 = new OTSPoint3D[127];
737 for (int i = 0; i < coordsHalf1.length; i++)
738 {
739 double angle = Math.PI * (1 + i) / (1 + coordsHalf1.length);
740 coordsHalf1[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
741 }
742 Lane[] lanes1 = LaneFactory.makeMultiLane(this.network, "FirstHalf", start, halfway, coordsHalf1, laneCount,
743 laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
744 OTSPoint3D[] coordsHalf2 = new OTSPoint3D[127];
745 for (int i = 0; i < coordsHalf2.length; i++)
746 {
747 double angle = Math.PI + Math.PI * (1 + i) / (1 + coordsHalf2.length);
748 coordsHalf2[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
749 }
750 Lane[] lanes2 = LaneFactory.makeMultiLane(this.network, "SecondHalf", halfway, start, coordsHalf2, laneCount,
751 laneType, this.speedLimit, this.simulator, LongitudinalDirectionality.DIR_PLUS);
752 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
753 {
754 this.paths.get(laneIndex).add(lanes1[laneIndex]);
755 this.paths.get(laneIndex).add(lanes2[laneIndex]);
756 }
757
758 int sensorNr = 0;
759 for (Lane lane : lanes1)
760 {
761 SimpleSilentSensor sensor = new SimpleSilentSensor("sensor " + ++sensorNr, lane,
762 new Length(10.0, LengthUnit.METER), RelativePosition.FRONT, imbAnimator);
763 lane.addSensor(sensor, gtuType);
764 }
765 for (Lane lane : lanes2)
766 {
767 SimpleSilentSensor sensor = new SimpleSilentSensor("sensor" + ++sensorNr, lane,
768 new Length(20.0, LengthUnit.METER), RelativePosition.REAR, imbAnimator);
769 lane.addSensor(sensor, gtuType);
770 }
771
772 double variability = (headway - 20) * headwayVariability;
773 System.out.println("headway is " + headway + " variability limit is " + variability);
774 Random random = new Random(12345);
775 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
776 {
777 double lane1Length = lanes1[laneIndex].getLength().getSI();
778 double trackLength = lane1Length + lanes2[laneIndex].getLength().getSI();
779 for (double pos = 0; pos <= trackLength - headway - variability;)
780 {
781 Lane lane = pos >= lane1Length ? lanes2[laneIndex] : lanes1[laneIndex];
782
783 double laneRelativePos = pos > lane1Length ? pos - lane1Length : pos;
784 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
785
786 generateCar(new Length(laneRelativePos, METER), lane, gtuType);
787 pos += actualHeadway;
788 }
789 }
790
791 this.simulator.scheduleEventAbs(new Time(9.999, SECOND), this, this, "drawGraphs", null);
792 }
793 catch (SimRuntimeException | NamingException | NetworkException | GTUException | OTSGeometryException
794 | PropertyException exception)
795 {
796 exception.printStackTrace();
797 }
798 if (null != panel)
799 {
800
801 ((AnimatorInterface) this.simulator).updateAnimation();
802 }
803 }
804
805
806
807
808 @SuppressWarnings("unchecked")
809 public void closeWindow()
810 {
811 try
812 {
813 ((Simulator<Time, Duration, OTSSimTimeDouble>) this.simulator).cleanUp();
814 }
815 catch (Exception exception)
816 {
817 exception.printStackTrace();
818 }
819 this.frame.dispose();
820 }
821
822
823
824
825 protected final void drawGraphs()
826 {
827 for (LaneBasedGTUSampler plot : this.plots)
828 {
829 plot.reGraph();
830 }
831
832 try
833 {
834 this.simulator.scheduleEventAbs(new Time(this.simulator.getSimulatorTime().get().getSI() + 10, SECOND), this,
835 this, "drawGraphs", null);
836 }
837 catch (SimRuntimeException exception)
838 {
839 exception.printStackTrace();
840 }
841
842 }
843
844
845
846
847
848
849
850
851
852
853
854
855 protected final void generateCar(final Length initialPosition, final Lane lane, final GTUType gtuType)
856 throws NamingException, NetworkException, SimRuntimeException, GTUException, OTSGeometryException
857 {
858
859
860 boolean generateTruck = this.randomGenerator.nextDouble() > this.carProbability;
861 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
862 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated), gtuType, vehicleLength,
863 new Length(1.8, METER), new Speed(200, KM_PER_HOUR), this.simulator, this.network);
864
865
866 LaneBasedStrategicalPlanner strategicalPlanner;
867 if (!generateTruck)
868 {
869 strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu);
870 }
871 else
872 {
873 strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu);
874 }
875
876
877 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
878 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
879 Speed initialSpeed = new Speed(0, KM_PER_HOUR);
880 gtu.initWithAnimation(strategicalPlanner, initialPositions, initialSpeed, DefaultCarAnimation.class,
881 this.gtuColorer);
882 }
883
884
885 @Override
886 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
887 {
888 return this.simulator;
889 }
890
891
892
893
894 public final List<LaneBasedGTUSampler> getPlots()
895 {
896 return this.plots;
897 }
898
899
900
901
902 public final Length getMinimumDistance()
903 {
904 return this.minimumDistance;
905 }
906
907
908
909
910
911
912 public void stopSimulator(final OTSDEVSSimulatorInterface theSimulator, final String errorMessage)
913 {
914 System.out.println("Error: " + errorMessage);
915 try
916 {
917 if (theSimulator.isRunning())
918 {
919 theSimulator.stop();
920 }
921 }
922 catch (SimRuntimeException exception)
923 {
924 exception.printStackTrace();
925 }
926 throw new Error(errorMessage);
927 }
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942 public static class SimpleSilentSensor extends AbstractSensor
943 {
944
945 private static final long serialVersionUID = 20150130L;
946
947
948
949
950
951
952
953
954
955
956
957
958 public SimpleSilentSensor(final String id, final Lane lane, final Length position,
959 final RelativePosition.TYPE triggerPosition, final OTSDEVSSimulatorInterface simulator)
960 throws NetworkException, OTSGeometryException
961 {
962 super(id, lane, position, triggerPosition, simulator, LaneBasedObject.makeGeometry(lane, position));
963 try
964 {
965 new SensorAnimation(this, position, simulator, Color.RED);
966 }
967 catch (RemoteException | NamingException exception)
968 {
969 exception.printStackTrace();
970 }
971 }
972
973
974 @Override
975 public final void triggerResponse(final LaneBasedGTU gtu)
976 {
977
978 }
979
980
981 @Override
982 public final String toString()
983 {
984 return "SimpleSilentSensor [Lane=" + this.getLane() + "]";
985 }
986
987
988 @Override
989 public AbstractSensor clone(final CrossSectionElement newCSE, final OTSSimulatorInterface newSimulator,
990 final boolean animation) throws NetworkException
991 {
992
993 return null;
994 }
995 }
996 }
997
998 }