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.old.XmlNetworkLaneParserOld;
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                 XmlNetworkLaneParserOld nlp = new XmlNetworkLaneParserOld(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 }