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