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.io.Serializable;
8   import java.net.URL;
9   import java.util.zip.ZipEntry;
10  import java.util.zip.ZipOutputStream;
11  
12  import javax.naming.NamingException;
13  import javax.swing.SwingUtilities;
14  
15  import org.djunits.unit.FrequencyUnit;
16  import org.djunits.value.vdouble.scalar.Duration;
17  import org.djunits.value.vdouble.scalar.Frequency;
18  import org.djunits.value.vdouble.scalar.Length;
19  import org.djunits.value.vdouble.scalar.Time;
20  import org.djutils.exceptions.Throw;
21  import org.djutils.io.URLResource;
22  import org.opentrafficsim.core.dsol.AbstractOTSModel;
23  import org.opentrafficsim.core.dsol.AbstractOTSSimulationApplication;
24  import org.opentrafficsim.core.dsol.OTSModelInterface;
25  import org.opentrafficsim.core.dsol.OTSSimulator;
26  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
27  import org.opentrafficsim.core.gtu.AbstractGTU;
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.OTSRoadNetwork;
34  import org.opentrafficsim.road.network.factory.xml.parser.XmlNetworkLaneParser;
35  import org.opentrafficsim.road.network.lane.CrossSectionLink;
36  import org.opentrafficsim.road.network.sampling.GtuData;
37  import org.opentrafficsim.road.network.sampling.LinkData;
38  import org.opentrafficsim.road.network.sampling.RoadSampler;
39  import org.opentrafficsim.road.network.sampling.data.TimeToCollision;
40  
41  import nl.tudelft.simulation.dsol.SimRuntimeException;
42  
43  /**
44   * Simulation for AHFE congress.
45   * <p>
46   * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
47   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
48   * <p>
49   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Feb 28, 2017 <br>
50   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
51   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
52   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
53   */
54  public class AHFESimulation extends AbstractOTSSimulationApplication
55  {
56      /** Warm-up time. */
57      static final Time WARMUP = Time.instantiateSI(360);
58  
59      /** Simulation time, including warm-up time. */
60      static final Time SIMEND = Time.instantiateSI(360 + 3600);
61  
62      /** Distance to not consider at start of the network. */
63      private static Length ignoreStart = Length.instantiateSI(2900); // Not 100m on pre-link, so 3000 total
64  
65      /** Distance to not consider at end of the network. */
66      private static Length ignoreEnd = Length.instantiateSI(1000);
67  
68      /** */
69      private static final long serialVersionUID = 20170228L;
70  
71      /**
72       * @param model OTSModelInterface; the model
73       */
74      public AHFESimulation(final OTSModelInterface model)
75      {
76          super(model);
77      }
78  
79      /**
80       * Main program.
81       * @param args String[]; the command line arguments
82       * @throws SimRuntimeException should never happen
83       */
84      @SuppressWarnings("checkstyle:methodlength")
85      public static void main(final String[] args) throws SimRuntimeException
86      {
87          AbstractGTU.ALIGNED = false;
88          long t1 = System.currentTimeMillis();
89          boolean autorun = true;
90          int replication = 1;
91          String anticipationStrategy = "none";
92          Duration reactionTime = Duration.instantiateSI(0.0);
93          Duration anticipationTime = Duration.ZERO;
94          double truckFraction = 0.05;
95          double distanceError = 0.0; // 0.05;
96          double speedError = 0.0; // 0.01;
97          double accelerationError = 0.0; // 0.10;
98          Frequency leftDemand = new Frequency(3500.0, FrequencyUnit.PER_HOUR);
99          Frequency rightDemand = new Frequency(3200.0, FrequencyUnit.PER_HOUR);
100         double leftFraction = 0.55;
101         String scenario = "test";
102 
103         for (String arg : args)
104         {
105             int equalsPos = arg.indexOf("=");
106             if (equalsPos >= 0)
107             {
108                 // set something
109                 String key = arg.substring(0, equalsPos);
110                 String value = arg.substring(equalsPos + 1);
111                 if ("autorun".equalsIgnoreCase(key))
112                 {
113                     if ("true".equalsIgnoreCase(value))
114                     {
115                         autorun = true;
116                     }
117                     else if ("false".equalsIgnoreCase(value))
118                     {
119                         autorun = false;
120                     }
121                     else
122                     {
123                         System.err.println("bad autorun value " + value + " (ignored)");
124                     }
125                 }
126                 else if ("replication".equalsIgnoreCase(key))
127                 {
128                     try
129                     {
130                         replication = Integer.parseInt(value);
131                     }
132                     catch (NumberFormatException nfe)
133                     {
134                         System.err.println("Ignoring unparsable replication number \"" + value + "\"");
135                     }
136                 }
137                 else if ("anticipation".equalsIgnoreCase(key))
138                 {
139                     if (value.equalsIgnoreCase("none") || value.equalsIgnoreCase("constant_speed")
140                             || value.equalsIgnoreCase("constant_acceleration"))
141                     {
142                         anticipationStrategy = value;
143                     }
144                     else
145                     {
146                         System.err.println("Ignoring unparsable anticipation \"" + value + "\"");
147                     }
148                 }
149                 else if ("reactiontime".equalsIgnoreCase(key))
150                 {
151                     try
152                     {
153                         reactionTime = Duration.instantiateSI(java.lang.Double.parseDouble(value));
154                     }
155                     catch (NumberFormatException nfe)
156                     {
157                         System.err.println("Ignoring unparsable reaction time \"" + value + "\"");
158                     }
159                 }
160                 else if ("anticipationtime".equalsIgnoreCase(key))
161                 {
162                     try
163                     {
164                         anticipationTime = Duration.instantiateSI(java.lang.Double.parseDouble(value));
165                     }
166                     catch (NumberFormatException nfe)
167                     {
168                         System.err.println("Ignoring unparsable anticipation time \"" + value + "\"");
169                     }
170                 }
171                 else if ("truckfraction".equalsIgnoreCase(key))
172                 {
173                     try
174                     {
175                         truckFraction = java.lang.Double.parseDouble(value);
176                         Throw.when(truckFraction < 0.0 || truckFraction > 1.0, IllegalArgumentException.class,
177                                 "Truck fraction must be between 0 and 1.");
178                     }
179                     catch (NumberFormatException nfe)
180                     {
181                         System.err.println("Ignoring unparsable truck fraction \"" + value + "\"");
182                     }
183                 }
184                 else if ("distanceerror".equalsIgnoreCase(key))
185                 {
186                     try
187                     {
188                         distanceError = java.lang.Double.parseDouble(value);
189                     }
190                     catch (NumberFormatException nfe)
191                     {
192                         System.err.println("Ignoring unparsable distance error \"" + value + "\"");
193                     }
194                 }
195                 else if ("speederror".equalsIgnoreCase(key))
196                 {
197                     try
198                     {
199                         speedError = java.lang.Double.parseDouble(value);
200                     }
201                     catch (NumberFormatException nfe)
202                     {
203                         System.err.println("Ignoring unparsable speed error \"" + value + "\"");
204                     }
205                 }
206                 else if ("accelerationerror".equalsIgnoreCase(key))
207                 {
208                     try
209                     {
210                         accelerationError = java.lang.Double.parseDouble(value);
211                     }
212                     catch (NumberFormatException nfe)
213                     {
214                         System.err.println("Ignoring unparsable acceleration error \"" + value + "\"");
215                     }
216                 }
217                 else if ("leftdemand".equalsIgnoreCase(key))
218                 {
219                     try
220                     {
221                         leftDemand = new Frequency(java.lang.Double.parseDouble(value), FrequencyUnit.PER_HOUR);
222                     }
223                     catch (NumberFormatException nfe)
224                     {
225                         System.err.println("Ignoring unparsable left demand \"" + value + "\"");
226                     }
227                 }
228                 else if ("rightdemand".equalsIgnoreCase(key))
229                 {
230                     try
231                     {
232                         rightDemand = new Frequency(java.lang.Double.parseDouble(value), FrequencyUnit.PER_HOUR);
233                     }
234                     catch (NumberFormatException nfe)
235                     {
236                         System.err.println("Ignoring unparsable right demand \"" + value + "\"");
237                     }
238                 }
239                 else if ("leftfraction".equalsIgnoreCase(key))
240                 {
241                     try
242                     {
243                         leftFraction = java.lang.Double.parseDouble(value);
244                     }
245                     catch (NumberFormatException nfe)
246                     {
247                         System.err.println("Ignoring unparsable left fraction \"" + value + "\"");
248                     }
249                 }
250                 else if ("scenario".equalsIgnoreCase(key))
251                 {
252                     scenario = value;
253                 }
254                 else
255                 {
256                     System.out.println("Ignoring unknown setting " + arg);
257                 }
258             }
259             else
260             {
261                 // not a flag
262                 System.err.println("Ignoring argument " + arg);
263             }
264         }
265         final boolean finalAutoRun = autorun;
266         final int finalReplication = replication;
267         final String finalAnticipationStrategy = anticipationStrategy;
268         final Duration finalReactionTime = reactionTime;
269         final Duration finalAnticipationTime = anticipationTime;
270         final double finalTruckFraction = truckFraction;
271         final double finalDistanceError = distanceError;
272         final double finalSpeedError = speedError;
273         final double finalAccelerationError = accelerationError;
274         final Frequency finalLeftDemand = leftDemand;
275         final Frequency finalRightDemand = rightDemand;
276         final double finalLeftFraction = leftFraction;
277         final String finalScenario = scenario;
278         SwingUtilities.invokeLater(new Runnable()
279         {
280             @Override
281             public void run()
282             {
283                 try
284                 {
285                     OTSSimulator simulator = new OTSSimulator("AHFESimulation");
286                     final AHFEModel ahfeModel = new AHFEModel(simulator, finalReplication, finalAnticipationStrategy,
287                             finalReactionTime, finalAnticipationTime, finalTruckFraction, finalDistanceError, finalSpeedError,
288                             finalAccelerationError, finalLeftDemand, finalRightDemand, finalLeftFraction);
289                     System.out.println("Setting up replication " + finalReplication);
290                     simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(SIMEND.si), ahfeModel, finalReplication);
291                     new AHFESimulation(ahfeModel);
292                     // 1 hour simulation run for testing
293                     if (finalAutoRun)
294                     {
295                         int lastReportedTime = -60;
296                         int reportTimeClick = 60;
297                         while (true)
298                         {
299                             int currentTime = (int) simulator.getSimulatorTime().si;
300                             if (currentTime >= lastReportedTime + reportTimeClick)
301                             {
302                                 lastReportedTime = currentTime / reportTimeClick * reportTimeClick;
303                                 System.out.println("time is " + simulator.getSimulatorTime());
304                             }
305                             try
306                             {
307                                 simulator.step();
308                             }
309                             catch (SimRuntimeException sre)
310                             {
311                                 if (sre.getCause() != null && sre.getCause().getCause() != null
312                                         && sre.getCause().getCause().getMessage().equals(
313                                                 "Model has calcalated a negative infinite or negative max value acceleration."))
314                                 {
315                                     System.err.println("Collision detected.");
316                                     String file = finalScenario + ".csv.zip";
317                                     FileOutputStream fos = null;
318                                     ZipOutputStream zos = null;
319                                     OutputStreamWriter osw = null;
320                                     BufferedWriter bw = null;
321                                     try
322                                     {
323                                         fos = new FileOutputStream(file);
324                                         zos = new ZipOutputStream(fos);
325                                         zos.putNextEntry(new ZipEntry(finalScenario + ".csv"));
326                                         osw = new OutputStreamWriter(zos);
327                                         bw = new BufferedWriter(osw);
328                                         bw.write("Collision");
329                                         bw.write(simulator.getSimulatorTime().toString());
330                                     }
331                                     catch (IOException exception2)
332                                     {
333                                         throw new RuntimeException("Could not write to file.", exception2);
334                                     }
335                                     // close file on fail
336                                     finally
337                                     {
338                                         try
339                                         {
340                                             if (bw != null)
341                                             {
342                                                 bw.close();
343                                             }
344                                             if (osw != null)
345                                             {
346                                                 osw.close();
347                                             }
348                                             if (zos != null)
349                                             {
350                                                 zos.close();
351                                             }
352                                             if (fos != null)
353                                             {
354                                                 fos.close();
355                                             }
356                                         }
357                                         catch (IOException ex)
358                                         {
359                                             ex.printStackTrace();
360                                         }
361                                     }
362                                 }
363                                 else
364                                 {
365                                     System.out.println("Simulation ends; time is " + simulator.getSimulatorTime());
366                                     if (ahfeModel.getSampler() != null)
367                                     {
368                                         ahfeModel.getSampler().getSamplerData().writeToFile(finalScenario + ".csv");
369                                     }
370                                 }
371                                 long t2 = System.currentTimeMillis();
372                                 System.out.println("Run took " + (t2 - t1) / 1000 + "s.");
373                                 System.exit(0);
374                                 break;
375                             }
376                         }
377 
378                     }
379                 }
380                 catch (SimRuntimeException | NamingException exception)
381                 {
382                     exception.printStackTrace();
383                 }
384             }
385         });
386     }
387 
388     /**
389      * The AHFE simulation model.
390      */
391     static class AHFEModel extends AbstractOTSModel
392     {
393         /** */
394         private static final long serialVersionUID = 20170228L;
395 
396         /** The network. */
397         private OTSRoadNetwork network;
398 
399         /** Replication. */
400         private final Integer replication;
401 
402         /** Anticipation strategy. */
403         private final String anticipationStrategy;
404 
405         /** Reaction time. */
406         private final Duration reactionTime;
407 
408         /** Future anticipation time. */
409         private final Duration anticipationTime;
410 
411         /** Truck fraction. */
412         private final double truckFraction;
413 
414         /** Distance error. */
415         private final double distanceError;
416 
417         /** Speed error. */
418         private final double speedError;
419 
420         /** Acceleration error. */
421         private final double accelerationError;
422 
423         /** Left demand. */
424         private final Frequency leftDemand;
425 
426         /** Right demand. */
427         private final Frequency rightDemand;
428 
429         /** Left fraction, per road. */
430         private final double leftFraction;
431 
432         /** Sampler. */
433         private Sampler<GtuData> sampler;
434 
435         /**
436          * @param simulator OTSSimulatorInterface; the simulator
437          * @param replication Integer; replication
438          * @param anticipationStrategy String; anticipation strategy
439          * @param reactionTime Duration; reaction time
440          * @param anticipationTime Duration; anticipation time
441          * @param truckFraction double; truck fraction
442          * @param distanceError double; distance error
443          * @param speedError double; speed error
444          * @param accelerationError double; acceleration error
445          * @param leftFraction double; left demand
446          * @param rightDemand Frequency; right demand
447          * @param leftDemand Frequency; left fraction, per road
448          */
449         @SuppressWarnings("checkstyle:parameternumber")
450         AHFEModel(final OTSSimulatorInterface simulator, final Integer replication, final String anticipationStrategy,
451                 final Duration reactionTime, final Duration anticipationTime, final double truckFraction,
452                 final double distanceError, final double speedError, final double accelerationError, final Frequency leftDemand,
453                 final Frequency rightDemand, final double leftFraction)
454         {
455             super(simulator);
456             this.replication = replication;
457             this.anticipationStrategy = anticipationStrategy;
458             this.reactionTime = reactionTime;
459             this.anticipationTime = anticipationTime;
460             this.truckFraction = truckFraction;
461             this.distanceError = distanceError;
462             this.speedError = speedError;
463             this.accelerationError = accelerationError;
464             this.leftDemand = leftDemand;
465             this.rightDemand = rightDemand;
466             this.leftFraction = leftFraction;
467         }
468 
469         /** {@inheritDoc} */
470         @SuppressWarnings("synthetic-access")
471         @Override
472         public void constructModel() throws SimRuntimeException
473         {
474             this.sampler = RoadSampler.build(this.network).registerExtendedDataType(new TimeToCollision()).create();
475             try
476             {
477                 URL xmlURL = URLResource.getResource("/AHFE/Network.xml");
478                 this.network = new OTSRoadNetwork("AHFE", true, getSimulator());
479                 XmlNetworkLaneParser.build(xmlURL, this.network, 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         /** {@inheritDoc} */
626         @Override
627         public Serializable getSourceId()
628         {
629             return "AHFESimulation.Model";
630         }
631 
632     }
633 }