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