1 package ahfe;
2
3 import java.awt.geom.Rectangle2D;
4 import java.awt.geom.Rectangle2D.Double;
5 import java.io.BufferedWriter;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.OutputStreamWriter;
10 import java.rmi.RemoteException;
11 import java.util.ArrayList;
12 import java.util.zip.ZipEntry;
13 import java.util.zip.ZipOutputStream;
14
15 import javax.naming.NamingException;
16 import javax.swing.SwingUtilities;
17
18 import org.djunits.unit.FrequencyUnit;
19 import org.djunits.value.vdouble.scalar.Duration;
20 import org.djunits.value.vdouble.scalar.Frequency;
21 import org.djunits.value.vdouble.scalar.Length;
22 import org.djunits.value.vdouble.scalar.Time;
23 import org.opentrafficsim.base.modelproperties.Property;
24 import org.opentrafficsim.base.modelproperties.PropertyException;
25 import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
26 import org.opentrafficsim.core.dsol.OTSModelInterface;
27 import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
28 import org.opentrafficsim.core.gtu.animation.GTUColorer;
29 import org.opentrafficsim.core.network.OTSNetwork;
30 import org.opentrafficsim.kpi.interfaces.LaneDataInterface;
31 import org.opentrafficsim.kpi.sampling.KpiGtuDirectionality;
32 import org.opentrafficsim.kpi.sampling.KpiLaneDirection;
33 import org.opentrafficsim.kpi.sampling.Sampler;
34 import org.opentrafficsim.kpi.sampling.SpaceTimeRegion;
35 import org.opentrafficsim.road.animation.AnimationToggles;
36 import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
37 import org.opentrafficsim.road.network.lane.CrossSectionLink;
38 import org.opentrafficsim.road.network.sampling.LinkData;
39 import org.opentrafficsim.road.network.sampling.RoadSampler;
40 import org.opentrafficsim.road.network.sampling.data.TimeToCollision;
41 import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
42 import org.opentrafficsim.simulationengine.OTSSimulationException;
43
44 import nl.tudelft.simulation.dsol.SimRuntimeException;
45 import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
46 import nl.tudelft.simulation.event.EventProducer;
47 import nl.tudelft.simulation.language.Throw;
48 import nl.tudelft.simulation.language.io.URLResource;
49
50
51
52
53
54
55
56
57
58
59
60
61 public class AHFESimulation extends AbstractWrappableAnimation
62 {
63
64
65 static final Time WARMUP = Time.createSI(360);
66
67
68 static final Time SIMEND = Time.createSI(360 + 3600);
69
70
71 private static Length ignoreStart = Length.createSI(2900);
72
73
74 private static Length ignoreEnd = Length.createSI(1000);
75
76
77 private static final long serialVersionUID = 20170228L;
78
79
80 private final Integer replication;
81
82
83 private final String anticipationStrategy;
84
85
86 private final Duration reactionTime;
87
88
89 private final Duration anticipationTime;
90
91
92 private final double truckFraction;
93
94
95 private final double distanceError;
96
97
98 private final double speedError;
99
100
101 private final double accelerationError;
102
103
104 private final Frequency leftDemand;
105
106
107 private final Frequency rightDemand;
108
109
110 private final double leftFraction;
111
112
113 Sampler sampler;
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 @SuppressWarnings("checkstyle:parameternumber")
129 public AHFESimulation(final Integer replication, final String anticipationStrategy, final Duration reactionTime,
130 final Duration anticipationTime, final double truckFraction, final double distanceError, final double speedError,
131 final double accelerationError, final Frequency leftDemand, final Frequency rightDemand, final double leftFraction)
132 {
133 super();
134 this.replication = replication;
135 this.anticipationStrategy = anticipationStrategy;
136 this.reactionTime = reactionTime;
137 this.anticipationTime = anticipationTime;
138 this.truckFraction = truckFraction;
139 this.distanceError = distanceError;
140 this.speedError = speedError;
141 this.accelerationError = accelerationError;
142 this.leftDemand = leftDemand;
143 this.rightDemand = rightDemand;
144 this.leftFraction = leftFraction;
145 }
146
147
148
149
150 public Integer getReplication()
151 {
152 return this.replication;
153 }
154
155
156
157
158 public String getAnticipationStrategy()
159 {
160 return this.anticipationStrategy;
161 }
162
163
164
165
166 public Duration getReactionTime()
167 {
168 return this.reactionTime;
169 }
170
171
172
173
174 public Duration getAnticipationTime()
175 {
176 return this.anticipationTime;
177 }
178
179
180
181
182 public double getTruckFraction()
183 {
184 return this.truckFraction;
185 }
186
187
188
189
190 public double getDistanceError()
191 {
192 return this.distanceError;
193 }
194
195
196
197
198 public double getSpeedError()
199 {
200 return this.speedError;
201 }
202
203
204
205
206 public double getAccelerationError()
207 {
208 return this.accelerationError;
209 }
210
211
212
213
214 public Frequency getLeftDemand()
215 {
216 return this.leftDemand;
217 }
218
219
220
221
222 public Frequency getRightDemand()
223 {
224 return this.rightDemand;
225 }
226
227
228
229
230 public double getLeftFraction()
231 {
232 return this.leftFraction;
233 }
234
235
236
237
238
239
240 public static void main(final String[] args) throws SimRuntimeException
241 {
242 long t1 = System.currentTimeMillis();
243 boolean autorun = false;
244 int replication = 1;
245 String anticipationStrategy = "none";
246 Duration reactionTime = Duration.createSI(0.0);
247 Duration anticipationTime = Duration.ZERO;
248 double truckFraction = 0.05;
249 double distanceError = 0.0;
250 double speedError = 0.0;
251 double accelerationError = 0.0;
252 Frequency leftDemand = new Frequency(3500.0, FrequencyUnit.PER_HOUR);
253 Frequency rightDemand = new Frequency(3200.0, FrequencyUnit.PER_HOUR);
254 double leftFraction = 0.55;
255 String scenario = "test";
256
257 for (String arg : args)
258 {
259 int equalsPos = arg.indexOf("=");
260 if (equalsPos >= 0)
261 {
262
263 String key = arg.substring(0, equalsPos);
264 String value = arg.substring(equalsPos + 1);
265 if ("autorun".equalsIgnoreCase(key))
266 {
267 if ("true".equalsIgnoreCase(value))
268 {
269 autorun = true;
270 }
271 else if ("false".equalsIgnoreCase(value))
272 {
273 autorun = false;
274 }
275 else
276 {
277 System.err.println("bad autorun value " + value + " (ignored)");
278 }
279 }
280 else if ("replication".equalsIgnoreCase(key))
281 {
282 try
283 {
284 replication = Integer.parseInt(value);
285 }
286 catch (NumberFormatException nfe)
287 {
288 System.err.println("Ignoring unparsable replication number \"" + value + "\"");
289 }
290 }
291 else if ("anticipation".equalsIgnoreCase(key))
292 {
293 if (value.equalsIgnoreCase("none") || value.equalsIgnoreCase("constant_speed")
294 || value.equalsIgnoreCase("constant_acceleration"))
295 {
296 anticipationStrategy = value;
297 }
298 else
299 {
300 System.err.println("Ignoring unparsable anticipation \"" + value + "\"");
301 }
302 }
303 else if ("reactiontime".equalsIgnoreCase(key))
304 {
305 try
306 {
307 reactionTime = Duration.createSI(java.lang.Double.parseDouble(value));
308 }
309 catch (NumberFormatException nfe)
310 {
311 System.err.println("Ignoring unparsable reaction time \"" + value + "\"");
312 }
313 }
314 else if ("anticipationtime".equalsIgnoreCase(key))
315 {
316 try
317 {
318 anticipationTime = Duration.createSI(java.lang.Double.parseDouble(value));
319 }
320 catch (NumberFormatException nfe)
321 {
322 System.err.println("Ignoring unparsable anticipation time \"" + value + "\"");
323 }
324 }
325 else if ("truckfraction".equalsIgnoreCase(key))
326 {
327 try
328 {
329 truckFraction = java.lang.Double.parseDouble(value);
330 Throw.when(truckFraction < 0.0 || truckFraction > 1.0, IllegalArgumentException.class,
331 "Truck fraction must be between 0 and 1.");
332 }
333 catch (NumberFormatException nfe)
334 {
335 System.err.println("Ignoring unparsable truck fraction \"" + value + "\"");
336 }
337 }
338 else if ("distanceerror".equalsIgnoreCase(key))
339 {
340 try
341 {
342 distanceError = java.lang.Double.parseDouble(value);
343 }
344 catch (NumberFormatException nfe)
345 {
346 System.err.println("Ignoring unparsable distance error \"" + value + "\"");
347 }
348 }
349 else if ("speederror".equalsIgnoreCase(key))
350 {
351 try
352 {
353 speedError = java.lang.Double.parseDouble(value);
354 }
355 catch (NumberFormatException nfe)
356 {
357 System.err.println("Ignoring unparsable speed error \"" + value + "\"");
358 }
359 }
360 else if ("accelerationerror".equalsIgnoreCase(key))
361 {
362 try
363 {
364 accelerationError = java.lang.Double.parseDouble(value);
365 }
366 catch (NumberFormatException nfe)
367 {
368 System.err.println("Ignoring unparsable acceleration error \"" + value + "\"");
369 }
370 }
371 else if ("leftdemand".equalsIgnoreCase(key))
372 {
373 try
374 {
375 leftDemand = new Frequency(java.lang.Double.parseDouble(value), FrequencyUnit.PER_HOUR);
376 }
377 catch (NumberFormatException nfe)
378 {
379 System.err.println("Ignoring unparsable left demand \"" + value + "\"");
380 }
381 }
382 else if ("rightdemand".equalsIgnoreCase(key))
383 {
384 try
385 {
386 rightDemand = new Frequency(java.lang.Double.parseDouble(value), FrequencyUnit.PER_HOUR);
387 }
388 catch (NumberFormatException nfe)
389 {
390 System.err.println("Ignoring unparsable right demand \"" + value + "\"");
391 }
392 }
393 else if ("leftfraction".equalsIgnoreCase(key))
394 {
395 try
396 {
397 leftFraction = java.lang.Double.parseDouble(value);
398 }
399 catch (NumberFormatException nfe)
400 {
401 System.err.println("Ignoring unparsable left fraction \"" + value + "\"");
402 }
403 }
404 else if ("scenario".equalsIgnoreCase(key))
405 {
406 scenario = value;
407 }
408 else
409 {
410 System.out.println("Ignoring unknown setting " + arg);
411 }
412 }
413 else
414 {
415
416 System.err.println("Ignoring argument " + arg);
417 }
418 }
419 final boolean finalAutoRun = autorun;
420 final int finalReplication = replication;
421 final String finalAnticipationStrategy = anticipationStrategy;
422 final Duration finalReactionTime = reactionTime;
423 final Duration finalAnticipationTime = anticipationTime;
424 final double finalTruckFraction = truckFraction;
425 final double finalDistanceError = distanceError;
426 final double finalSpeedError = speedError;
427 final double finalAccelerationError = accelerationError;
428 final Frequency finalLeftDemand = leftDemand;
429 final Frequency finalRightDemand = rightDemand;
430 final double finalLeftFraction = leftFraction;
431 final String finalScenario = scenario;
432 SwingUtilities.invokeLater(new Runnable()
433 {
434 @Override
435 public void run()
436 {
437 try
438 {
439 AHFESimulation model = new AHFESimulation(finalReplication, finalAnticipationStrategy, finalReactionTime,
440 finalAnticipationTime, finalTruckFraction, finalDistanceError, finalSpeedError,
441 finalAccelerationError, finalLeftDemand, finalRightDemand, finalLeftFraction);
442 System.out.println("Setting up replication " + finalReplication);
443 model.setNextReplication(finalReplication);
444
445 model.buildAnimator(Time.ZERO, Duration.ZERO, Duration.createSI(SIMEND.si), new ArrayList<Property<?>>(),
446 null, true);
447 if (finalAutoRun)
448 {
449 int lastReportedTime = -1;
450 int reportTimeClick = 60;
451 while (true)
452 {
453 int currentTime = (int) model.getSimulator().getSimulatorTime().getTime().si;
454 if (currentTime >= lastReportedTime + reportTimeClick)
455 {
456 lastReportedTime = currentTime / reportTimeClick * reportTimeClick;
457 System.out.println("time is " + model.getSimulator().getSimulatorTime().getTime());
458 }
459 try
460 {
461 model.getSimulator().step();
462 }
463 catch (SimRuntimeException sre)
464 {
465 if (sre.getCause() != null && sre.getCause().getCause() != null
466 && sre.getCause().getCause().getMessage().equals(
467 "Model has calcalated a negative infinite or negative max value acceleration."))
468 {
469 System.err.println("Collision detected.");
470 String file = finalScenario + ".csv.zip";
471 FileOutputStream fos = null;
472 ZipOutputStream zos = null;
473 OutputStreamWriter osw = null;
474 BufferedWriter bw = null;
475 try
476 {
477 fos = new FileOutputStream(file);
478 zos = new ZipOutputStream(fos);
479 zos.putNextEntry(new ZipEntry(finalScenario + ".csv"));
480 osw = new OutputStreamWriter(zos);
481 bw = new BufferedWriter(osw);
482 bw.write("Collision");
483 bw.write(model.getSimulator().getSimulatorTime().getTime().toString());
484 }
485 catch (IOException exception2)
486 {
487 throw new RuntimeException("Could not write to file.", exception2);
488 }
489
490 finally
491 {
492 try
493 {
494 if (bw != null)
495 {
496 bw.close();
497 }
498 if (osw != null)
499 {
500 osw.close();
501 }
502 if (zos != null)
503 {
504 zos.close();
505 }
506 if (fos != null)
507 {
508 fos.close();
509 }
510 }
511 catch (IOException ex)
512 {
513 ex.printStackTrace();
514 }
515 }
516 }
517 else
518 {
519 System.out.println(
520 "Simulation ends; time is " + model.getSimulator().getSimulatorTime().getTime());
521 if (model.sampler != null)
522 {
523 model.sampler.writeToFile(finalScenario + ".csv");
524 }
525 }
526 long t2 = System.currentTimeMillis();
527 System.out.println("Run took " + (t2 - t1) / 1000 + "s.");
528 System.exit(0);
529 break;
530 }
531 }
532
533 }
534 }
535 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException
536 | RemoteException exception)
537 {
538 exception.printStackTrace();
539 }
540 }
541 });
542 }
543
544
545 private SimulatorInterface<Time, Duration, OTSSimTimeDouble> simulator;
546
547
548 @Override
549 public final String shortName()
550 {
551 return "AFFE Simulation";
552 }
553
554
555 @Override
556 public final String description()
557 {
558 return "Simulation for AHFE congress";
559 }
560
561
562 @Override
563 protected final OTSModelInterface makeModel(final GTUColorer colorer) throws OTSSimulationException
564 {
565 return new AHFEModel(colorer);
566 }
567
568
569 @Override
570 protected final void addAnimationToggles()
571 {
572 AnimationToggles.setTextAnimationTogglesStandard(this);
573 }
574
575
576 @Override
577 protected final Double makeAnimationRectangle()
578 {
579 return new Rectangle2D.Double(-50, -100, 8050, 150);
580 }
581
582
583
584
585 class AHFEModel extends EventProducer implements OTSModelInterface
586 {
587
588
589 private static final long serialVersionUID = 20170228L;
590
591
592 private OTSNetwork network;
593
594
595 private final GTUColorer colorer;
596
597
598
599
600 AHFEModel(final GTUColorer colorer)
601 {
602 this.colorer = colorer;
603 }
604
605
606 @SuppressWarnings("synthetic-access")
607 @Override
608 public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> theSimulator)
609 throws SimRuntimeException, RemoteException
610 {
611 AHFESimulation.this.simulator = theSimulator;
612
613 AHFESimulation.this.sampler = new RoadSampler((OTSDEVSSimulatorInterface) theSimulator);
614 AHFESimulation.this.sampler.registerExtendedDataType(new TimeToCollision());
615 try
616 {
617 InputStream stream = URLResource.getResourceAsStream("/AHFE/Network.xml");
618 XmlNetworkLaneParser nlp = new XmlNetworkLaneParser((OTSDEVSSimulatorInterface) theSimulator);
619 this.network = new OTSNetwork("AHFE");
620 nlp.build(stream, this.network);
621
622
623 LinkData linkData = new LinkData((CrossSectionLink) this.network.getLink("LEFTIN"));
624 registerLinkToSampler(linkData, ignoreStart, linkData.getLength());
625 linkData = new LinkData((CrossSectionLink) this.network.getLink("RIGHTIN"));
626 registerLinkToSampler(linkData, ignoreStart, linkData.getLength());
627 linkData = new LinkData((CrossSectionLink) this.network.getLink("CONVERGE"));
628 registerLinkToSampler(linkData, Length.ZERO, linkData.getLength());
629 linkData = new LinkData((CrossSectionLink) this.network.getLink("WEAVING"));
630 registerLinkToSampler(linkData, Length.ZERO, linkData.getLength());
631 linkData = new LinkData((CrossSectionLink) this.network.getLink("END"));
632 registerLinkToSampler(linkData, Length.ZERO, linkData.getLength().minus(ignoreEnd));
633
634
635 AHFEUtil.createDemand(this.network, this.colorer, (OTSDEVSSimulatorInterface) theSimulator, getReplication(),
636 getAnticipationStrategy(), getReactionTime(), getAnticipationTime(), getTruckFraction(), SIMEND,
637 getLeftDemand(), getRightDemand(), getLeftFraction(), getDistanceError(), getSpeedError(),
638 getAccelerationError());
639
640 }
641 catch (Exception exception)
642 {
643 exception.printStackTrace();
644 }
645 }
646
647
648
649
650
651
652
653 private void registerLinkToSampler(final LinkData linkData, final Length startDistance, final Length endDistance)
654 {
655 for (LaneDataInterface laneData : linkData.getLaneDatas())
656 {
657 Length start = laneData.getLength().multiplyBy(startDistance.si / linkData.getLength().si);
658 Length end = laneData.getLength().multiplyBy(endDistance.si / linkData.getLength().si);
659 AHFESimulation.this.sampler.registerSpaceTimeRegion(new SpaceTimeRegion(
660 new KpiLaneDirection(laneData, KpiGtuDirectionality.DIR_PLUS), start, end, WARMUP, SIMEND));
661 }
662 }
663
664
665 @SuppressWarnings("synthetic-access")
666 @Override
667 public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
668 {
669 return AHFESimulation.this.simulator;
670 }
671
672
673 @Override
674 public OTSNetwork getNetwork()
675 {
676 return this.network;
677 }
678
679 }
680
681
682
683
684
685 public final SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator()
686 {
687 return this.simulator;
688 }
689
690 }