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().getSamplerData().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 = RoadSampler.build(this.network).registerExtendedDataType(new TimeToCollision()).create();
475 try
476 {
477 URL xmlURL = URLResource.getResource("/AHFE/Network.xml");
478 this.network = new OTSRoadNetwork("AHFE", true, getSimulator());
479 XmlNetworkLaneParser.build(xmlURL, this.network, false);
480
481
482 LinkData linkData = new LinkData((CrossSectionLink) this.network.getLink("LEFTIN"));
483 registerLinkToSampler(linkData, ignoreStart, linkData.getLength());
484 linkData = new LinkData((CrossSectionLink) this.network.getLink("RIGHTIN"));
485 registerLinkToSampler(linkData, ignoreStart, linkData.getLength());
486 linkData = new LinkData((CrossSectionLink) this.network.getLink("CONVERGE"));
487 registerLinkToSampler(linkData, Length.ZERO, linkData.getLength());
488 linkData = new LinkData((CrossSectionLink) this.network.getLink("WEAVING"));
489 registerLinkToSampler(linkData, Length.ZERO, linkData.getLength());
490 linkData = new LinkData((CrossSectionLink) this.network.getLink("END"));
491 registerLinkToSampler(linkData, Length.ZERO, linkData.getLength().minus(ignoreEnd));
492
493
494 AHFEUtil.createDemand(this.network, null, this.simulator, getReplication(), getAnticipationStrategy(),
495 getReactionTime(), getAnticipationTime(), getTruckFraction(), SIMEND, getLeftDemand(), getRightDemand(),
496 getLeftFraction(), getDistanceError(), getSpeedError(), getAccelerationError());
497
498 }
499 catch (Exception exception)
500 {
501 exception.printStackTrace();
502 }
503 }
504
505
506
507
508
509
510
511 private void registerLinkToSampler(final LinkData linkData, final Length startDistance, final Length endDistance)
512 {
513 for (LaneDataInterface laneData : linkData.getLaneDatas())
514 {
515 Length start = laneData.getLength().times(startDistance.si / linkData.getLength().si);
516 Length end = laneData.getLength().times(endDistance.si / linkData.getLength().si);
517 this.sampler.registerSpaceTimeRegion(new SpaceTimeRegion(
518 new KpiLaneDirection(laneData, KpiGtuDirectionality.DIR_PLUS), start, end, WARMUP, SIMEND));
519 }
520 }
521
522
523 @Override
524 public OTSRoadNetwork getNetwork()
525 {
526 return this.network;
527 }
528
529
530
531
532 public Integer getReplication()
533 {
534 return this.replication;
535 }
536
537
538
539
540 public String getAnticipationStrategy()
541 {
542 return this.anticipationStrategy;
543 }
544
545
546
547
548 public Duration getReactionTime()
549 {
550 return this.reactionTime;
551 }
552
553
554
555
556 public Duration getAnticipationTime()
557 {
558 return this.anticipationTime;
559 }
560
561
562
563
564 public double getTruckFraction()
565 {
566 return this.truckFraction;
567 }
568
569
570
571
572 public double getDistanceError()
573 {
574 return this.distanceError;
575 }
576
577
578
579
580 public double getSpeedError()
581 {
582 return this.speedError;
583 }
584
585
586
587
588 public double getAccelerationError()
589 {
590 return this.accelerationError;
591 }
592
593
594
595
596 public Frequency getLeftDemand()
597 {
598 return this.leftDemand;
599 }
600
601
602
603
604 public Frequency getRightDemand()
605 {
606 return this.rightDemand;
607 }
608
609
610
611
612 public double getLeftFraction()
613 {
614 return this.leftFraction;
615 }
616
617
618
619
620 public final Sampler<GtuData> getSampler()
621 {
622 return this.sampler;
623 }
624
625
626 @Override
627 public Serializable getSourceId()
628 {
629 return "AHFESimulation.Model";
630 }
631
632 }
633 }