View Javadoc
1   package 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.ArrayList;
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.opentrafficsim.base.modelproperties.Property;
21  import org.opentrafficsim.base.modelproperties.PropertyException;
22  import org.opentrafficsim.core.dsol.OTSModelInterface;
23  import org.opentrafficsim.core.gtu.AbstractGTU;
24  import org.opentrafficsim.core.network.OTSNetwork;
25  import org.opentrafficsim.kpi.interfaces.LaneDataInterface;
26  import org.opentrafficsim.kpi.sampling.KpiGtuDirectionality;
27  import org.opentrafficsim.kpi.sampling.KpiLaneDirection;
28  import org.opentrafficsim.kpi.sampling.Sampler;
29  import org.opentrafficsim.kpi.sampling.SpaceTimeRegion;
30  import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
31  import org.opentrafficsim.road.network.lane.CrossSectionLink;
32  import org.opentrafficsim.road.network.sampling.GtuData;
33  import org.opentrafficsim.road.network.sampling.LinkData;
34  import org.opentrafficsim.road.network.sampling.RoadSampler;
35  import org.opentrafficsim.road.network.sampling.data.TimeToCollision;
36  import org.opentrafficsim.simulationengine.AbstractWrappableSimulation;
37  import org.opentrafficsim.simulationengine.OTSSimulationException;
38  
39  import nl.tudelft.simulation.dsol.SimRuntimeException;
40  import nl.tudelft.simulation.dsol.simtime.SimTimeDoubleUnit;
41  import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
42  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
43  import nl.tudelft.simulation.event.EventProducer;
44  import nl.tudelft.simulation.language.Throw;
45  import nl.tudelft.simulation.language.io.URLResource;
46  
47  /**
48   * Simulation for AHFE congress.
49   * <p>
50   * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
51   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
52   * <p>
53   * @version $Revision$, $LastChangedDate$, by $Author$, initial version Feb 28, 2017 <br>
54   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
55   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
56   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
57   */
58  public class AHFESimulation extends AbstractWrappableSimulation
59  {
60  
61      /** Warm-up time. */
62      static final Time WARMUP = Time.createSI(360);
63  
64      /** Simulation time, including warm-up time. */
65      static final Time SIMEND = Time.createSI(360 + 3600);
66  
67      /** Distance to not consider at start of the network. */
68      private static Length ignoreStart = Length.createSI(2900); // Not 100m on pre-link, so 3000 total
69  
70      /** Distance to not consider at end of the network. */
71      private static Length ignoreEnd = Length.createSI(1000);
72  
73      /** */
74      private static final long serialVersionUID = 20170228L;
75  
76      /** Replication. */
77      private final Integer replication;
78  
79      /** Anticipation strategy. */
80      private final String anticipationStrategy;
81  
82      /** Reaction time. */
83      private final Duration reactionTime;
84  
85      /** Future anticipation time. */
86      private final Duration anticipationTime;
87  
88      /** Truck fraction. */
89      private final double truckFraction;
90  
91      /** Distance error. */
92      private final double distanceError;
93  
94      /** Speed error. */
95      private final double speedError;
96  
97      /** Acceleration error. */
98      private final double accelerationError;
99  
100     /** Left demand. */
101     private final Frequency leftDemand;
102 
103     /** Right demand. */
104     private final Frequency rightDemand;
105 
106     /** Left fraction, per road. */
107     private final double leftFraction;
108 
109     /** Sampler. */
110     Sampler<GtuData> sampler;
111 
112     /**
113      * @param replication replication
114      * @param anticipationStrategy anticipation strategy
115      * @param reactionTime reaction time
116      * @param anticipationTime anticipation time
117      * @param truckFraction truck fraction
118      * @param distanceError distance error
119      * @param speedError speed error
120      * @param accelerationError acceleration error
121      * @param leftFraction left demand
122      * @param rightDemand right demand
123      * @param leftDemand left fraction, per road
124      */
125     @SuppressWarnings("checkstyle:parameternumber")
126     public AHFESimulation(final Integer replication, final String anticipationStrategy, final Duration reactionTime,
127             final Duration anticipationTime, final double truckFraction, final double distanceError, final double speedError,
128             final double accelerationError, final Frequency leftDemand, final Frequency rightDemand, final double leftFraction)
129     {
130         super();
131         this.replication = replication;
132         this.anticipationStrategy = anticipationStrategy;
133         this.reactionTime = reactionTime;
134         this.anticipationTime = anticipationTime;
135         this.truckFraction = truckFraction;
136         this.distanceError = distanceError;
137         this.speedError = speedError;
138         this.accelerationError = accelerationError;
139         this.leftDemand = leftDemand;
140         this.rightDemand = rightDemand;
141         this.leftFraction = leftFraction;
142     }
143 
144     /**
145      * @return replication.
146      */
147     public Integer getReplication()
148     {
149         return this.replication;
150     }
151 
152     /**
153      * @return anticipationStrategy.
154      */
155     public String getAnticipationStrategy()
156     {
157         return this.anticipationStrategy;
158     }
159 
160     /**
161      * @return reactionTime.
162      */
163     public Duration getReactionTime()
164     {
165         return this.reactionTime;
166     }
167 
168     /**
169      * @return anticipationTime.
170      */
171     public Duration getAnticipationTime()
172     {
173         return this.anticipationTime;
174     }
175 
176     /**
177      * @return truckFraction.
178      */
179     public double getTruckFraction()
180     {
181         return this.truckFraction;
182     }
183 
184     /**
185      * @return distanceError.
186      */
187     public double getDistanceError()
188     {
189         return this.distanceError;
190     }
191 
192     /**
193      * @return speedError.
194      */
195     public double getSpeedError()
196     {
197         return this.speedError;
198     }
199 
200     /**
201      * @return accelerationError.
202      */
203     public double getAccelerationError()
204     {
205         return this.accelerationError;
206     }
207 
208     /**
209      * @return leftDemand.
210      */
211     public Frequency getLeftDemand()
212     {
213         return this.leftDemand;
214     }
215 
216     /**
217      * @return rightDemand.
218      */
219     public Frequency getRightDemand()
220     {
221         return this.rightDemand;
222     }
223 
224     /**
225      * @return leftFraction.
226      */
227     public double getLeftFraction()
228     {
229         return this.leftFraction;
230     }
231 
232     /**
233      * Main program.
234      * @param args String[]; the command line arguments
235      * @throws SimRuntimeException should never happen
236      */
237     public static void main(final String[] args) throws SimRuntimeException
238     {
239         AbstractGTU.ALIGNED = false;
240         long t1 = System.currentTimeMillis();
241         boolean autorun = false;
242         int replication = 1;
243         String anticipationStrategy = "none";
244         Duration reactionTime = Duration.createSI(0.0);
245         Duration anticipationTime = Duration.ZERO;
246         double truckFraction = 0.05;
247         double distanceError = 0.0; // 0.05;
248         double speedError = 0.0; // 0.01;
249         double accelerationError = 0.0; // 0.10;
250         Frequency leftDemand = new Frequency(3500.0, FrequencyUnit.PER_HOUR);
251         Frequency rightDemand = new Frequency(3200.0, FrequencyUnit.PER_HOUR);
252         double leftFraction = 0.55;
253         String scenario = "test";
254 
255         for (String arg : args)
256         {
257             int equalsPos = arg.indexOf("=");
258             if (equalsPos >= 0)
259             {
260                 // set something
261                 String key = arg.substring(0, equalsPos);
262                 String value = arg.substring(equalsPos + 1);
263                 if ("autorun".equalsIgnoreCase(key))
264                 {
265                     if ("true".equalsIgnoreCase(value))
266                     {
267                         autorun = true;
268                     }
269                     else if ("false".equalsIgnoreCase(value))
270                     {
271                         autorun = false;
272                     }
273                     else
274                     {
275                         System.err.println("bad autorun value " + value + " (ignored)");
276                     }
277                 }
278                 else if ("replication".equalsIgnoreCase(key))
279                 {
280                     try
281                     {
282                         replication = Integer.parseInt(value);
283                     }
284                     catch (NumberFormatException nfe)
285                     {
286                         System.err.println("Ignoring unparsable replication number \"" + value + "\"");
287                     }
288                 }
289                 else if ("anticipation".equalsIgnoreCase(key))
290                 {
291                     if (value.equalsIgnoreCase("none") || value.equalsIgnoreCase("constant_speed")
292                             || value.equalsIgnoreCase("constant_acceleration"))
293                     {
294                         anticipationStrategy = value;
295                     }
296                     else
297                     {
298                         System.err.println("Ignoring unparsable anticipation \"" + value + "\"");
299                     }
300                 }
301                 else if ("reactiontime".equalsIgnoreCase(key))
302                 {
303                     try
304                     {
305                         reactionTime = Duration.createSI(java.lang.Double.parseDouble(value));
306                     }
307                     catch (NumberFormatException nfe)
308                     {
309                         System.err.println("Ignoring unparsable reaction time \"" + value + "\"");
310                     }
311                 }
312                 else if ("anticipationtime".equalsIgnoreCase(key))
313                 {
314                     try
315                     {
316                         anticipationTime = Duration.createSI(java.lang.Double.parseDouble(value));
317                     }
318                     catch (NumberFormatException nfe)
319                     {
320                         System.err.println("Ignoring unparsable anticipation time \"" + value + "\"");
321                     }
322                 }
323                 else if ("truckfraction".equalsIgnoreCase(key))
324                 {
325                     try
326                     {
327                         truckFraction = java.lang.Double.parseDouble(value);
328                         Throw.when(truckFraction < 0.0 || truckFraction > 1.0, IllegalArgumentException.class,
329                                 "Truck fraction must be between 0 and 1.");
330                     }
331                     catch (NumberFormatException nfe)
332                     {
333                         System.err.println("Ignoring unparsable truck fraction \"" + value + "\"");
334                     }
335                 }
336                 else if ("distanceerror".equalsIgnoreCase(key))
337                 {
338                     try
339                     {
340                         distanceError = java.lang.Double.parseDouble(value);
341                     }
342                     catch (NumberFormatException nfe)
343                     {
344                         System.err.println("Ignoring unparsable distance error \"" + value + "\"");
345                     }
346                 }
347                 else if ("speederror".equalsIgnoreCase(key))
348                 {
349                     try
350                     {
351                         speedError = java.lang.Double.parseDouble(value);
352                     }
353                     catch (NumberFormatException nfe)
354                     {
355                         System.err.println("Ignoring unparsable speed error \"" + value + "\"");
356                     }
357                 }
358                 else if ("accelerationerror".equalsIgnoreCase(key))
359                 {
360                     try
361                     {
362                         accelerationError = java.lang.Double.parseDouble(value);
363                     }
364                     catch (NumberFormatException nfe)
365                     {
366                         System.err.println("Ignoring unparsable acceleration error \"" + value + "\"");
367                     }
368                 }
369                 else if ("leftdemand".equalsIgnoreCase(key))
370                 {
371                     try
372                     {
373                         leftDemand = new Frequency(java.lang.Double.parseDouble(value), FrequencyUnit.PER_HOUR);
374                     }
375                     catch (NumberFormatException nfe)
376                     {
377                         System.err.println("Ignoring unparsable left demand \"" + value + "\"");
378                     }
379                 }
380                 else if ("rightdemand".equalsIgnoreCase(key))
381                 {
382                     try
383                     {
384                         rightDemand = new Frequency(java.lang.Double.parseDouble(value), FrequencyUnit.PER_HOUR);
385                     }
386                     catch (NumberFormatException nfe)
387                     {
388                         System.err.println("Ignoring unparsable right demand \"" + value + "\"");
389                     }
390                 }
391                 else if ("leftfraction".equalsIgnoreCase(key))
392                 {
393                     try
394                     {
395                         leftFraction = java.lang.Double.parseDouble(value);
396                     }
397                     catch (NumberFormatException nfe)
398                     {
399                         System.err.println("Ignoring unparsable left fraction \"" + value + "\"");
400                     }
401                 }
402                 else if ("scenario".equalsIgnoreCase(key))
403                 {
404                     scenario = value;
405                 }
406                 else
407                 {
408                     System.out.println("Ignoring unknown setting " + arg);
409                 }
410             }
411             else
412             {
413                 // not a flag
414                 System.err.println("Ignoring argument " + arg);
415             }
416         }
417         final boolean finalAutoRun = autorun;
418         final int finalReplication = replication;
419         final String finalAnticipationStrategy = anticipationStrategy;
420         final Duration finalReactionTime = reactionTime;
421         final Duration finalAnticipationTime = anticipationTime;
422         final double finalTruckFraction = truckFraction;
423         final double finalDistanceError = distanceError;
424         final double finalSpeedError = speedError;
425         final double finalAccelerationError = accelerationError;
426         final Frequency finalLeftDemand = leftDemand;
427         final Frequency finalRightDemand = rightDemand;
428         final double finalLeftFraction = leftFraction;
429         final String finalScenario = scenario;
430         SwingUtilities.invokeLater(new Runnable()
431         {
432             @Override
433             public void run()
434             {
435                 try
436                 {
437                     AHFESimulation model = new AHFESimulation(finalReplication, finalAnticipationStrategy, finalReactionTime,
438                             finalAnticipationTime, finalTruckFraction, finalDistanceError, finalSpeedError,
439                             finalAccelerationError, finalLeftDemand, finalRightDemand, finalLeftFraction);
440                     System.out.println("Setting up replication " + finalReplication);
441                     model.setNextReplication(finalReplication);
442                     // 1 hour simulation run for testing
443                     model.buildSimulator(Time.ZERO, Duration.ZERO, Duration.createSI(SIMEND.si), new ArrayList<Property<?>>());
444                     if (finalAutoRun)
445                     {
446                         int lastReportedTime = -60;
447                         int reportTimeClick = 60;
448                         while (true)
449                         {
450                             int currentTime = (int) model.getSimulator().getSimulatorTime().si;
451                             if (currentTime >= lastReportedTime + reportTimeClick)
452                             {
453                                 lastReportedTime = currentTime / reportTimeClick * reportTimeClick;
454                                 System.out.println("time is " + model.getSimulator().getSimulatorTime());
455                             }
456                             try
457                             {
458                                 model.getSimulator().step();
459                             }
460                             catch (SimRuntimeException sre)
461                             {
462                                 if (sre.getCause() != null && sre.getCause().getCause() != null
463                                         && sre.getCause().getCause().getMessage().equals(
464                                                 "Model has calcalated a negative infinite or negative max value acceleration."))
465                                 {
466                                     System.err.println("Collision detected.");
467                                     String file = finalScenario + ".csv.zip";
468                                     FileOutputStream fos = null;
469                                     ZipOutputStream zos = null;
470                                     OutputStreamWriter osw = null;
471                                     BufferedWriter bw = null;
472                                     try
473                                     {
474                                         fos = new FileOutputStream(file);
475                                         zos = new ZipOutputStream(fos);
476                                         zos.putNextEntry(new ZipEntry(finalScenario + ".csv"));
477                                         osw = new OutputStreamWriter(zos);
478                                         bw = new BufferedWriter(osw);
479                                         bw.write("Collision");
480                                         bw.write(model.getSimulator().getSimulatorTime().toString());
481                                     }
482                                     catch (IOException exception2)
483                                     {
484                                         throw new RuntimeException("Could not write to file.", exception2);
485                                     }
486                                     // close file on fail
487                                     finally
488                                     {
489                                         try
490                                         {
491                                             if (bw != null)
492                                             {
493                                                 bw.close();
494                                             }
495                                             if (osw != null)
496                                             {
497                                                 osw.close();
498                                             }
499                                             if (zos != null)
500                                             {
501                                                 zos.close();
502                                             }
503                                             if (fos != null)
504                                             {
505                                                 fos.close();
506                                             }
507                                         }
508                                         catch (IOException ex)
509                                         {
510                                             ex.printStackTrace();
511                                         }
512                                     }
513                                 }
514                                 else
515                                 {
516                                     System.out.println("Simulation ends; time is " + model.getSimulator().getSimulatorTime());
517                                     if (model.sampler != null)
518                                     {
519                                         model.sampler.writeToFile(finalScenario + ".csv");
520                                     }
521                                 }
522                                 long t2 = System.currentTimeMillis();
523                                 System.out.println("Run took " + (t2 - t1) / 1000 + "s.");
524                                 System.exit(0);
525                                 break;
526                             }
527                         }
528 
529                     }
530                 }
531                 catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
532                 {
533                     exception.printStackTrace();
534                 }
535             }
536         });
537     }
538 
539     /** The simulator. */
540     private SimulatorInterface<Time, Duration, SimTimeDoubleUnit> simulator;
541 
542     /** {@inheritDoc} */
543     @Override
544     public final String shortName()
545     {
546         return "AFFE Simulation";
547     }
548 
549     /** {@inheritDoc} */
550     @Override
551     public final String description()
552     {
553         return "Simulation for AHFE congress";
554     }
555 
556     /** {@inheritDoc} */
557     @Override
558     protected final OTSModelInterface makeModel() throws OTSSimulationException
559     {
560         return new AHFEModel();
561     }
562 
563     /**
564      * The AHFE simulation model.
565      */
566     class AHFEModel extends EventProducer implements OTSModelInterface
567     {
568 
569         /** */
570         private static final long serialVersionUID = 20170228L;
571 
572         /** The network. */
573         private OTSNetwork network;
574 
575         /**
576          */
577         AHFEModel()
578         {
579         }
580 
581         /** {@inheritDoc} */
582         @SuppressWarnings("synthetic-access")
583         @Override
584         public void constructModel(final SimulatorInterface<Time, Duration, SimTimeDoubleUnit> theSimulator)
585                 throws SimRuntimeException
586         {
587             AHFESimulation.this.simulator = theSimulator;
588 
589             AHFESimulation.this.sampler = new RoadSampler((DEVSSimulatorInterface.TimeDoubleUnit) theSimulator);
590             AHFESimulation.this.sampler.registerExtendedDataType(new TimeToCollision());
591             try
592             {
593                 // InputStream stream = URLResource.getResourceAsStream("/AHFE/Network.xml"); // Running from eclipse
594                 URL stream = URLResource.getResource("./Network.xml"); // Running Jar
595                 XmlNetworkLaneParser nlp = new XmlNetworkLaneParser((DEVSSimulatorInterface.TimeDoubleUnit) theSimulator);
596                 this.network = new OTSNetwork("AHFE");
597                 nlp.build(stream, this.network, true);
598 
599                 // Space-time regions for sampler
600                 LinkData linkData = new LinkData((CrossSectionLink) this.network.getLink("LEFTIN"));
601                 registerLinkToSampler(linkData, ignoreStart, linkData.getLength());
602                 linkData = new LinkData((CrossSectionLink) this.network.getLink("RIGHTIN"));
603                 registerLinkToSampler(linkData, ignoreStart, linkData.getLength());
604                 linkData = new LinkData((CrossSectionLink) this.network.getLink("CONVERGE"));
605                 registerLinkToSampler(linkData, Length.ZERO, linkData.getLength());
606                 linkData = new LinkData((CrossSectionLink) this.network.getLink("WEAVING"));
607                 registerLinkToSampler(linkData, Length.ZERO, linkData.getLength());
608                 linkData = new LinkData((CrossSectionLink) this.network.getLink("END"));
609                 registerLinkToSampler(linkData, Length.ZERO, linkData.getLength().minus(ignoreEnd));
610 
611                 // Generator
612                 AHFEUtil.createDemand(this.network, null, (DEVSSimulatorInterface.TimeDoubleUnit) theSimulator,
613                         getReplication(), getAnticipationStrategy(), getReactionTime(), getAnticipationTime(),
614                         getTruckFraction(), SIMEND, getLeftDemand(), getRightDemand(), getLeftFraction(), getDistanceError(),
615                         getSpeedError(), getAccelerationError());
616 
617             }
618             catch (Exception exception)
619             {
620                 exception.printStackTrace();
621             }
622         }
623 
624         /**
625          * Register a link to the sampler, so data is sampled there.
626          * @param linkData link data
627          * @param startDistance start distance on link
628          * @param endDistance end distance on link
629          */
630         private void registerLinkToSampler(final LinkData linkData, final Length startDistance, final Length endDistance)
631         {
632             for (LaneDataInterface laneData : linkData.getLaneDatas())
633             {
634                 Length start = laneData.getLength().multiplyBy(startDistance.si / linkData.getLength().si);
635                 Length end = laneData.getLength().multiplyBy(endDistance.si / linkData.getLength().si);
636                 AHFESimulation.this.sampler.registerSpaceTimeRegion(new SpaceTimeRegion(
637                         new KpiLaneDirection(laneData, KpiGtuDirectionality.DIR_PLUS), start, end, WARMUP, SIMEND));
638             }
639         }
640 
641         /** {@inheritDoc} */
642         @SuppressWarnings("synthetic-access")
643         @Override
644         public SimulatorInterface<Time, Duration, SimTimeDoubleUnit> getSimulator()
645         {
646             return AHFESimulation.this.simulator;
647         }
648 
649         /** {@inheritDoc} */
650         @Override
651         public OTSNetwork getNetwork()
652         {
653             return this.network;
654         }
655 
656     }
657 
658     /**
659      * Retrieve the simulator.
660      * @return SimulatorInterface&lt;Time, Duration, SimTimeDoubleUnit&gt;; the simulator.
661      */
662     public final SimulatorInterface<Time, Duration, SimTimeDoubleUnit> getSimulator()
663     {
664         return this.simulator;
665     }
666 
667 }