1 package org.opentrafficsim.road.animation;
2
3 import java.awt.Color;
4 import java.rmi.RemoteException;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.Map;
8
9 import javax.naming.NamingException;
10
11 import org.djunits.value.vdouble.scalar.Duration;
12 import org.djunits.value.vdouble.scalar.Time;
13 import org.opentrafficsim.base.modelproperties.Property;
14 import org.opentrafficsim.core.dsol.OTSModelInterface;
15 import org.opentrafficsim.core.geometry.OTSGeometryException;
16 import org.opentrafficsim.core.gtu.GTUType;
17 import org.opentrafficsim.core.gtu.Try;
18 import org.opentrafficsim.core.gtu.animation.GTUColorer;
19 import org.opentrafficsim.core.network.LateralDirectionality;
20 import org.opentrafficsim.core.network.Link;
21 import org.opentrafficsim.core.network.Node;
22 import org.opentrafficsim.core.network.OTSLink;
23 import org.opentrafficsim.core.network.OTSNetwork;
24 import org.opentrafficsim.core.network.OTSNode;
25 import org.opentrafficsim.core.network.animation.LinkAnimation;
26 import org.opentrafficsim.core.network.animation.NodeAnimation;
27 import org.opentrafficsim.road.gtu.animation.DefaultSwitchableGTUColorer;
28 import org.opentrafficsim.road.gtu.generator.GTUGenerator;
29 import org.opentrafficsim.road.network.animation.LaneAnimation;
30 import org.opentrafficsim.road.network.animation.ShoulderAnimation;
31 import org.opentrafficsim.road.network.animation.StripeAnimation;
32 import org.opentrafficsim.road.network.animation.StripeAnimation.TYPE;
33 import org.opentrafficsim.road.network.lane.CrossSectionElement;
34 import org.opentrafficsim.road.network.lane.CrossSectionLink;
35 import org.opentrafficsim.road.network.lane.Lane;
36 import org.opentrafficsim.road.network.lane.Shoulder;
37 import org.opentrafficsim.road.network.lane.Stripe;
38 import org.opentrafficsim.road.network.lane.object.SpeedSign;
39 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
40 import org.opentrafficsim.simulationengine.AbstractWrappableSimulation;
41 import org.opentrafficsim.simulationengine.OTSSimulationException;
42 import org.opentrafficsim.simulationengine.SimpleSimulatorInterface;
43
44 import nl.tudelft.simulation.dsol.SimRuntimeException;
45 import nl.tudelft.simulation.dsol.simtime.SimTimeDoubleUnit;
46 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
47 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
48 import nl.tudelft.simulation.event.EventInterface;
49 import nl.tudelft.simulation.event.EventListenerInterface;
50 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
51 import nl.tudelft.simulation.jstats.streams.StreamInterface;
52 import nl.tudelft.simulation.language.Throw;
53
54
55
56
57
58
59
60
61
62
63
64
65 public abstract class AbstractSimulationScript implements EventListenerInterface
66 {
67
68
69 private final String name;
70
71
72 private final String description;
73
74
75 private DEVSSimulatorInterface.TimeDoubleUnit simulator;
76
77
78 private OTSNetwork network;
79
80
81 private final Map<String, String> props = new HashMap<>();
82
83
84 private GTUColorer gtuColorer = new DefaultSwitchableGTUColorer();
85
86
87
88
89
90
91
92 protected AbstractSimulationScript(final String name, final String description, final String[] properties)
93 {
94 this.name = name;
95 this.description = description;
96 this.props.put("seed", "1");
97 this.props.put("startTime", "0");
98 this.props.put("warmupTime", "0");
99 this.props.put("simulationTime", "3600");
100 this.props.put("autorun", "false");
101 setDefaultProperties();
102 for (int i = 0; i < properties.length; i += 2)
103 {
104 this.props.put(properties[i], properties[i + 1]);
105 }
106 }
107
108
109
110
111
112
113 public final void setProperty(final String propertyName, final Object propertyValue)
114 {
115 this.props.put(propertyName, propertyValue.toString());
116 }
117
118
119
120
121
122
123 public final String getProperty(final String propertyName)
124 {
125 String p = this.props.get(propertyName);
126 Throw.when(p == null, IllegalStateException.class, "Property %s is not given.", propertyName);
127 return p;
128 }
129
130
131
132
133
134
135 public final double getDoubleProperty(final String propertyName)
136 {
137 return Double.parseDouble(getProperty(propertyName));
138 }
139
140
141
142
143
144
145 public final boolean getBooleanProperty(final String propertyName)
146 {
147 return Boolean.parseBoolean(getProperty(propertyName));
148 }
149
150
151
152
153
154
155 public final int getIntegerProperty(final String propertyName)
156 {
157 return Integer.parseInt(getProperty(propertyName));
158 }
159
160
161
162
163
164
165 public final Duration getDurationProperty(final String propertyName)
166 {
167 return Duration.createSI(getDoubleProperty(propertyName));
168 }
169
170
171
172
173
174
175 public final Time getTimeProperty(final String propertyName)
176 {
177 return Time.createSI(getDoubleProperty(propertyName));
178 }
179
180
181
182
183
184 public final void setGtuColorer(final GTUColorer colorer)
185 {
186 this.gtuColorer = colorer;
187 }
188
189
190
191
192
193 public final GTUColorer getGtuColorer()
194 {
195 return this.gtuColorer;
196 }
197
198
199
200
201 public final void start()
202 {
203 Time startTime = getTimeProperty("startTime");
204 Duration warmupTime = getDurationProperty("warmupTime");
205 Duration simulationTime = getDurationProperty("simulationTime");
206 if (getBooleanProperty("autorun"))
207 {
208
209 ScriptSimulation scriptSimulation = this.new ScriptSimulation();
210 try
211 {
212 DEVSSimulatorInterface.TimeDoubleUnit sim =
213 scriptSimulation.buildSimulator(startTime, warmupTime, simulationTime, new ArrayList<Property<?>>());
214 sim.addListener(this, SimulatorInterface.END_OF_REPLICATION_EVENT);
215 double tReport = 60.0;
216 Time t = sim.getSimulatorTime();
217 while (t.si < simulationTime.si)
218 {
219 sim.step();
220 t = sim.getSimulatorTime();
221 if (t.si >= tReport)
222 {
223 System.out.println("Simulation time is " + t);
224 tReport += 60.0;
225 }
226 }
227 sim.stop();
228 }
229 catch (Exception exception)
230 {
231 exception.printStackTrace();
232 }
233 }
234 else
235 {
236 Try.execute(() -> new ScriptAnimation().buildAnimator(startTime, warmupTime, simulationTime,
237 new ArrayList<Property<?>>(), null, true), RuntimeException.class, "Exception from properties.");
238 }
239 }
240
241
242 @Override
243 public final void notify(final EventInterface event) throws RemoteException
244 {
245 if (event.getType().equals(SimulatorInterface.END_OF_REPLICATION_EVENT))
246 {
247 onSimulationEnd();
248
249 AbstractSimulationScript.this.simulator.removeListener(AbstractSimulationScript.this,
250 SimulatorInterface.END_OF_REPLICATION_EVENT);
251 }
252 }
253
254
255
256
257
258 public final DEVSSimulatorInterface.TimeDoubleUnit getSimulator()
259 {
260 return AbstractSimulationScript.this.simulator;
261 }
262
263
264
265
266
267 public final OTSNetwork getNetwork()
268 {
269 return AbstractSimulationScript.this.network;
270 }
271
272
273
274
275
276
277
278 protected void animateNetwork(final OTSNetwork net)
279 {
280 try
281 {
282 for (Node node : net.getNodeMap().values())
283 {
284 new NodeAnimation(node, AbstractSimulationScript.this.simulator);
285 }
286 for (Link link : net.getLinkMap().values())
287 {
288 new LinkAnimation(link, AbstractSimulationScript.this.simulator, 0.5f);
289 if (link instanceof CrossSectionLink)
290 {
291 for (CrossSectionElement element : ((CrossSectionLink) link).getCrossSectionElementList())
292 {
293 if (element instanceof Lane)
294 {
295 new LaneAnimation((Lane) element, AbstractSimulationScript.this.simulator, Color.GRAY.brighter(),
296 false);
297 }
298 else if (element instanceof Shoulder)
299 {
300 new ShoulderAnimation((Shoulder) element, AbstractSimulationScript.this.simulator, Color.DARK_GRAY);
301 }
302 else if (element instanceof Stripe)
303 {
304 Stripe stripe = (Stripe) element;
305 TYPE type;
306 if (stripe.isPermeable(GTUType.CAR, LateralDirectionality.LEFT))
307 {
308 type = stripe.isPermeable(GTUType.CAR, LateralDirectionality.RIGHT) ? TYPE.DASHED
309 : TYPE.LEFTONLY;
310 }
311 else
312 {
313 type = stripe.isPermeable(GTUType.CAR, LateralDirectionality.RIGHT) ? TYPE.RIGHTONLY
314 : TYPE.SOLID;
315 }
316 new StripeAnimation((Stripe) element, AbstractSimulationScript.this.simulator, type);
317 }
318 }
319 }
320 }
321 }
322 catch (RemoteException | NamingException | OTSGeometryException exception)
323 {
324 throw new RuntimeException("Exception while creating network animation.", exception);
325 }
326 }
327
328
329
330
331
332 protected void addAnimationToggles(final AbstractWrappableAnimation animation)
333 {
334 AnimationToggles.setIconAnimationTogglesFull(animation);
335 animation.toggleAnimationClass(OTSLink.class);
336 animation.toggleAnimationClass(OTSNode.class);
337 animation.toggleAnimationClass(GTUGenerator.class);
338 animation.showAnimationClass(SpeedSign.class);
339 }
340
341
342
343
344
345 protected void addTabs(final SimpleSimulatorInterface sim)
346 {
347
348 }
349
350
351
352
353 protected void setDefaultProperties()
354 {
355
356 }
357
358
359
360
361 protected void onSimulationEnd()
362 {
363
364 }
365
366
367
368
369
370
371 protected void setupDemo(final AbstractWrappableAnimation animation, final OTSNetwork net)
372 {
373
374 }
375
376
377
378
379
380
381
382
383
384
385 protected abstract OTSNetwork setupSimulation(DEVSSimulatorInterface.TimeDoubleUnit sim) throws Exception;
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401 class ScriptSimulation extends AbstractWrappableSimulation
402 {
403
404 private static final long serialVersionUID = 20180409L;
405
406
407 @SuppressWarnings("synthetic-access")
408 @Override
409 public String shortName()
410 {
411 return AbstractSimulationScript.this.name;
412 }
413
414
415 @SuppressWarnings("synthetic-access")
416 @Override
417 public String description()
418 {
419 return AbstractSimulationScript.this.description;
420 }
421
422
423 @Override
424 protected OTSModelInterface makeModel() throws OTSSimulationException
425 {
426 return new ScriptModel();
427 }
428 }
429
430
431
432
433
434
435
436
437
438
439
440
441
442 class ScriptAnimation extends AbstractWrappableAnimation
443 {
444
445 private static final long serialVersionUID = 20180409L;
446
447
448 @SuppressWarnings("synthetic-access")
449 @Override
450 public String shortName()
451 {
452 return AbstractSimulationScript.this.name;
453 }
454
455
456 @SuppressWarnings("synthetic-access")
457 @Override
458 public String description()
459 {
460 return AbstractSimulationScript.this.description;
461 }
462
463
464 @Override
465 protected OTSModelInterface makeModel() throws OTSSimulationException
466 {
467 return new ScriptModel();
468 }
469
470
471 @Override
472 protected final void addAnimationToggles()
473 {
474 AbstractSimulationScript.this.addAnimationToggles(this);
475 }
476
477
478 @Override
479 protected final void addTabs(final SimpleSimulatorInterface sim)
480 {
481 AbstractSimulationScript.this.addTabs(sim);
482 }
483
484
485 @SuppressWarnings("synthetic-access")
486 @Override
487 public final GTUColorer getColorer()
488 {
489 return AbstractSimulationScript.this.gtuColorer;
490 }
491
492
493 @Override
494 protected void setupDemo(final AbstractWrappableAnimation animation, final OTSNetwork net)
495 {
496 AbstractSimulationScript.this.setupDemo(animation, net);
497 }
498
499 }
500
501
502
503
504
505
506
507
508
509
510
511
512
513 private class ScriptModel implements OTSModelInterface
514 {
515
516 private static final long serialVersionUID = 20180409L;
517
518
519
520
521 ScriptModel()
522 {
523 }
524
525
526 @SuppressWarnings("synthetic-access")
527 @Override
528 public void constructModel(final SimulatorInterface<Time, Duration, SimTimeDoubleUnit> sim)
529 throws SimRuntimeException
530 {
531 AbstractSimulationScript.this.simulator = (DEVSSimulatorInterface.TimeDoubleUnit) sim;
532 Map<String, StreamInterface> streams = new HashMap<>();
533 StreamInterface stream = new MersenneTwister(Long.valueOf(getProperty("seed")));
534 streams.put("generation", stream);
535 sim.getReplication().setStreams(streams);
536 AbstractSimulationScript.this.network =
537 Try.assign(() -> AbstractSimulationScript.this.setupSimulation((DEVSSimulatorInterface.TimeDoubleUnit) sim),
538 RuntimeException.class, "Exception while setting up simulation.");
539 try
540 {
541 AbstractSimulationScript.this.simulator.addListener(AbstractSimulationScript.this,
542 SimulatorInterface.END_OF_REPLICATION_EVENT);
543 }
544 catch (RemoteException exception)
545 {
546 throw new SimRuntimeException(exception);
547 }
548 }
549
550
551 @SuppressWarnings("synthetic-access")
552 @Override
553 public SimulatorInterface<Time, Duration, SimTimeDoubleUnit> getSimulator()
554 {
555 return AbstractSimulationScript.this.simulator;
556 }
557
558
559 @SuppressWarnings("synthetic-access")
560 @Override
561 public OTSNetwork getNetwork()
562 {
563 return AbstractSimulationScript.this.network;
564 }
565 }
566
567 }