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.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.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.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   * Simulation for AHFE congress.
44   * <p>
45   * Copyright (c) 2013-2019 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.createSI(360);
57  
58      /** Simulation time, including warm-up time. */
59      static final Time SIMEND = Time.createSI(360 + 3600);
60  
61      /** Distance to not consider at start of the network. */
62      private static Length ignoreStart = Length.createSI(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.createSI(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.createSI(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.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                 // 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.createSI(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 
478                 InputStream stream = URLResource.getResourceAsStream("/AHFE/Network.xml"); // Running from eclipse
479                 // URL stream = URLResource.getResource("./Network.xml"); // Running Jar
480                 XmlNetworkLaneParserOld nlp = new XmlNetworkLaneParserOld(this.simulator);
481                 this.network = new OTSRoadNetwork("AHFE", true);
482                 nlp.build(stream, this.network, true);
483 
484                 // Space-time regions for sampler
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                 // Generator
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          * Register a link to the sampler, so data is sampled there.
510          * @param linkData LinkData; link data
511          * @param startDistance Length; start distance on link
512          * @param endDistance Length; end distance on link
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         /** {@inheritDoc} */
526         @Override
527         public OTSRoadNetwork getNetwork()
528         {
529             return this.network;
530         }
531 
532         /**
533          * @return replication.
534          */
535         public Integer getReplication()
536         {
537             return this.replication;
538         }
539 
540         /**
541          * @return anticipationStrategy.
542          */
543         public String getAnticipationStrategy()
544         {
545             return this.anticipationStrategy;
546         }
547 
548         /**
549          * @return reactionTime.
550          */
551         public Duration getReactionTime()
552         {
553             return this.reactionTime;
554         }
555 
556         /**
557          * @return anticipationTime.
558          */
559         public Duration getAnticipationTime()
560         {
561             return this.anticipationTime;
562         }
563 
564         /**
565          * @return truckFraction.
566          */
567         public double getTruckFraction()
568         {
569             return this.truckFraction;
570         }
571 
572         /**
573          * @return distanceError.
574          */
575         public double getDistanceError()
576         {
577             return this.distanceError;
578         }
579 
580         /**
581          * @return speedError.
582          */
583         public double getSpeedError()
584         {
585             return this.speedError;
586         }
587 
588         /**
589          * @return accelerationError.
590          */
591         public double getAccelerationError()
592         {
593             return this.accelerationError;
594         }
595 
596         /**
597          * @return leftDemand.
598          */
599         public Frequency getLeftDemand()
600         {
601             return this.leftDemand;
602         }
603 
604         /**
605          * @return rightDemand.
606          */
607         public Frequency getRightDemand()
608         {
609             return this.rightDemand;
610         }
611 
612         /**
613          * @return leftFraction.
614          */
615         public double getLeftFraction()
616         {
617             return this.leftFraction;
618         }
619 
620         /**
621          * @return sampler
622          */
623         public final Sampler<GtuData> getSampler()
624         {
625             return this.sampler;
626         }
627 
628     }
629 }