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