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