View Javadoc
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   * Simulation for AHFE congress.
44   * <p>
45   * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
46   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
47   * <p>
48   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Feb 28, 2017 <br>
49   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
50   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
51   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
52   */
53  public class AHFESimulation extends AbstractOTSSimulationApplication
54  {
55      /** Warm-up time. */
56      static final Time WARMUP = Time.instantiateSI(360);
57  
58      /** Simulation time, including warm-up time. */
59      static final Time SIMEND = Time.instantiateSI(360 + 3600);
60  
61      /** Distance to not consider at start of the network. */
62      private static Length ignoreStart = Length.instantiateSI(2900); // Not 100m on pre-link, so 3000 total
63  
64      /** Distance to not consider at end of the network. */
65      private static Length ignoreEnd = Length.instantiateSI(1000);
66  
67      /** */
68      private static final long serialVersionUID = 20170228L;
69  
70      /**
71       * @param model OTSModelInterface; the model
72       */
73      public AHFESimulation(final OTSModelInterface model)
74      {
75          super(model);
76      }
77  
78      /**
79       * Main program.
80       * @param args String[]; the command line arguments
81       * @throws SimRuntimeException should never happen
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; // 0.05;
95          double speedError = 0.0; // 0.01;
96          double accelerationError = 0.0; // 0.10;
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                 // set something
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                 // not a flag
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                     // 1 hour simulation run for testing
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                                     // close file on fail
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      * The AHFE simulation model.
389      */
390     static class AHFEModel extends AbstractOTSModel
391     {
392         /** */
393         private static final long serialVersionUID = 20170228L;
394 
395         /** The network. */
396         private OTSRoadNetwork network;
397 
398         /** Replication. */
399         private final Integer replication;
400 
401         /** Anticipation strategy. */
402         private final String anticipationStrategy;
403 
404         /** Reaction time. */
405         private final Duration reactionTime;
406 
407         /** Future anticipation time. */
408         private final Duration anticipationTime;
409 
410         /** Truck fraction. */
411         private final double truckFraction;
412 
413         /** Distance error. */
414         private final double distanceError;
415 
416         /** Speed error. */
417         private final double speedError;
418 
419         /** Acceleration error. */
420         private final double accelerationError;
421 
422         /** Left demand. */
423         private final Frequency leftDemand;
424 
425         /** Right demand. */
426         private final Frequency rightDemand;
427 
428         /** Left fraction, per road. */
429         private final double leftFraction;
430 
431         /** Sampler. */
432         private Sampler<GtuData> sampler;
433 
434         /**
435          * @param simulator OTSSimulatorInterface; the simulator
436          * @param replication Integer; replication
437          * @param anticipationStrategy String; anticipation strategy
438          * @param reactionTime Duration; reaction time
439          * @param anticipationTime Duration; anticipation time
440          * @param truckFraction double; truck fraction
441          * @param distanceError double; distance error
442          * @param speedError double; speed error
443          * @param accelerationError double; acceleration error
444          * @param leftFraction double; left demand
445          * @param rightDemand Frequency; right demand
446          * @param leftDemand Frequency; left fraction, per road
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         /** {@inheritDoc} */
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                 // Space-time regions for sampler
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                 // Generator
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          * Register a link to the sampler, so data is sampled there.
507          * @param linkData LinkData; link data
508          * @param startDistance Length; start distance on link
509          * @param endDistance Length; end distance on link
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         /** {@inheritDoc} */
523         @Override
524         public OTSRoadNetwork getNetwork()
525         {
526             return this.network;
527         }
528 
529         /**
530          * @return replication.
531          */
532         public Integer getReplication()
533         {
534             return this.replication;
535         }
536 
537         /**
538          * @return anticipationStrategy.
539          */
540         public String getAnticipationStrategy()
541         {
542             return this.anticipationStrategy;
543         }
544 
545         /**
546          * @return reactionTime.
547          */
548         public Duration getReactionTime()
549         {
550             return this.reactionTime;
551         }
552 
553         /**
554          * @return anticipationTime.
555          */
556         public Duration getAnticipationTime()
557         {
558             return this.anticipationTime;
559         }
560 
561         /**
562          * @return truckFraction.
563          */
564         public double getTruckFraction()
565         {
566             return this.truckFraction;
567         }
568 
569         /**
570          * @return distanceError.
571          */
572         public double getDistanceError()
573         {
574             return this.distanceError;
575         }
576 
577         /**
578          * @return speedError.
579          */
580         public double getSpeedError()
581         {
582             return this.speedError;
583         }
584 
585         /**
586          * @return accelerationError.
587          */
588         public double getAccelerationError()
589         {
590             return this.accelerationError;
591         }
592 
593         /**
594          * @return leftDemand.
595          */
596         public Frequency getLeftDemand()
597         {
598             return this.leftDemand;
599         }
600 
601         /**
602          * @return rightDemand.
603          */
604         public Frequency getRightDemand()
605         {
606             return this.rightDemand;
607         }
608 
609         /**
610          * @return leftFraction.
611          */
612         public double getLeftFraction()
613         {
614             return this.leftFraction;
615         }
616 
617         /**
618          * @return sampler
619          */
620         public final Sampler<GtuData> getSampler()
621         {
622             return this.sampler;
623         }
624 
625     }
626 }