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().getSamplerData().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 = RoadSampler.build(this.network).registerExtendedDataType(new TimeToCollision()).create();
495 try
496 {
497 URL xmlURL = URLResource.getResource("/AHFE/Network.xml");
498 this.network = new OTSRoadNetwork("AHFE", true, getSimulator());
499 XmlNetworkLaneParser.build(xmlURL, this.network, false);
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().times(startDistance.si / linkData.getLength().si);
537 Length end = laneData.getLength().times(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 OTSRoadNetwork 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 @Override
648 public Serializable getSourceId()
649 {
650 return "AHFEAnimation.Model";
651 }
652
653 }
654
655 }