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.net.URL;
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.kpi.interfaces.LaneDataInterface;
28  import org.opentrafficsim.kpi.sampling.KpiGtuDirectionality;
29  import org.opentrafficsim.kpi.sampling.KpiLaneDirection;
30  import org.opentrafficsim.kpi.sampling.Sampler;
31  import org.opentrafficsim.kpi.sampling.SpaceTimeRegion;
32  import org.opentrafficsim.road.network.OTSRoadNetwork;
33  import org.opentrafficsim.road.network.factory.xml.parser.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.instantiateSI(360);
57  
58      
59      static final Time SIMEND = Time.instantiateSI(360 + 3600);
60  
61      
62      private static Length ignoreStart = Length.instantiateSI(2900); 
63  
64      
65      private static Length ignoreEnd = Length.instantiateSI(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.instantiateSI(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.instantiateSI(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.instantiateSI(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.instantiateSI(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 OTSRoadNetwork 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                 URL xmlURL = URLResource.getResource("/AHFE/Network.xml");
478                 this.network = new OTSRoadNetwork("AHFE", true);
479                 XmlNetworkLaneParser.build(xmlURL, this.network, getSimulator(), 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 }