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