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