1   package org.opentrafficsim.demo;
2   
3   import static org.opentrafficsim.core.gtu.GTUType.CAR;
4   
5   import java.util.ArrayList;
6   import java.util.LinkedHashSet;
7   import java.util.List;
8   import java.util.Random;
9   import java.util.Set;
10  
11  import org.djunits.unit.LengthUnit;
12  import org.djunits.unit.UNITS;
13  import org.djunits.value.vdouble.scalar.Acceleration;
14  import org.djunits.value.vdouble.scalar.Length;
15  import org.djunits.value.vdouble.scalar.Speed;
16  import org.opentrafficsim.base.parameters.Parameters;
17  import org.opentrafficsim.core.dsol.AbstractOTSModel;
18  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
19  import org.opentrafficsim.core.geometry.OTSGeometryException;
20  import org.opentrafficsim.core.geometry.OTSPoint3D;
21  import org.opentrafficsim.core.gtu.GTUDirectionality;
22  import org.opentrafficsim.core.gtu.GTUException;
23  import org.opentrafficsim.core.gtu.GTUType;
24  import org.opentrafficsim.core.network.NetworkException;
25  import org.opentrafficsim.core.network.OTSNetwork;
26  import org.opentrafficsim.core.network.OTSNode;
27  import org.opentrafficsim.core.network.route.Route;
28  import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
29  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
30  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
31  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
32  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
33  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
34  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
35  import org.opentrafficsim.road.network.factory.LaneFactory;
36  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
37  import org.opentrafficsim.road.network.lane.Lane;
38  import org.opentrafficsim.road.network.lane.LaneType;
39  
40  import nl.tudelft.simulation.dsol.SimRuntimeException;
41  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDouble;
42  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDoubleScalar;
43  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException;
44  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterMap;
45  import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
46  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
47  import nl.tudelft.simulation.jstats.streams.StreamInterface;
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  public class CircularLaneModel extends AbstractOTSModel implements UNITS
60  {
61      
62      private static final long serialVersionUID = 20141121L;
63  
64      
65      private int carsCreated = 0;
66  
67      
68      private GTUType gtuType = CAR;
69  
70      
71      private double carProbability;
72  
73      
74      private Length minimumDistance = new Length(0, METER);
75  
76      
77      private Speed speedLimit = new Speed(100, KM_PER_HOUR);
78  
79      
80      private List<Lane> path = new ArrayList<>();
81  
82      
83      private Lane lane1;
84  
85      
86      private Lane lane2;
87  
88      
89      private StreamInterface stream = new MersenneTwister(12345);
90  
91      
92      private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
93  
94      
95      private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
96  
97      
98      private Parameters parametersCar;
99  
100     
101     private Parameters parametersTruck;
102 
103     
104     private final OTSNetwork network = new OTSNetwork("network");
105 
106     
107 
108 
109     public CircularLaneModel(final OTSSimulatorInterface simulator)
110     {
111         super(simulator);
112         makeInputParameterMap();
113     }
114 
115     
116 
117 
118     public void makeInputParameterMap()
119     {
120         try
121         {
122             InputParameterHelper.makeInputParameterMapCarTruck(this.inputParameterMap, 4.0);
123             InputParameterMap genericMap = (InputParameterMap) this.inputParameterMap.get("generic");
124 
125             genericMap.add(new InputParameterDoubleScalar<LengthUnit, Length>("trackLength", "Track length",
126                     "Track length (circumfence of the track)", Length.createSI(1000.0), Length.createSI(500.0),
127                     Length.createSI(2000.0), true, true, "%.0f", 1.0));
128             genericMap.add(new InputParameterDouble("densityMean", "Mean density (veh / km)",
129                     "mean density of the vehicles (vehicles per kilometer)", 30.0, 5.0, 45.0, true, true, "%.0f", 2.0));
130             genericMap.add(new InputParameterDouble("densityVariability", "Density variability",
131                     "Variability of the denisty: variability * (headway - 20) meters", 0.0, 0.0, 1.0, true, true, "%.00f",
132                     3.0));
133         }
134         catch (InputParameterException exception)
135         {
136             exception.printStackTrace();
137         }
138     }
139 
140     
141     @Override
142     public void constructModel() throws SimRuntimeException
143     {
144         try
145         {
146             this.carProbability = (double) getInputParameter("generic.carProbability");
147             double radius = ((Length) getInputParameter("generic.trackLength")).si / 2 / Math.PI;
148             double headway = 1000.0 / (double) getInputParameter("generic.densityMean");
149             double headwayVariability = (double) getInputParameter("generic.densityVariability");
150 
151             this.parametersCar = InputParameterHelper.getParametersCar(getInputParameterMap());
152             this.parametersTruck = InputParameterHelper.getParametersTruck(getInputParameterMap());
153 
154             this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
155                     new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
156             this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
157                     new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
158 
159             LaneType laneType = LaneType.TWO_WAY_LANE;
160             OTSNode start = new OTSNode(this.network, "Start", new OTSPoint3D(radius, 0, 0));
161             OTSNode halfway = new OTSNode(this.network, "Halfway", new OTSPoint3D(-radius, 0, 0));
162 
163             OTSPoint3D[] coordsHalf1 = new OTSPoint3D[127];
164             for (int i = 0; i < coordsHalf1.length; i++)
165             {
166                 double angle = Math.PI * (1 + i) / (1 + coordsHalf1.length);
167                 coordsHalf1[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
168             }
169             this.lane1 = LaneFactory.makeMultiLane(this.network, "Lane1", start, halfway, coordsHalf1, 1, laneType,
170                     this.speedLimit, this.simulator)[0];
171             this.path.add(this.lane1);
172 
173             OTSPoint3D[] coordsHalf2 = new OTSPoint3D[127];
174             for (int i = 0; i < coordsHalf2.length; i++)
175             {
176                 double angle = Math.PI + Math.PI * (1 + i) / (1 + coordsHalf2.length);
177                 coordsHalf2[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
178             }
179             this.lane2 = LaneFactory.makeMultiLane(this.network, "Lane2", halfway, start, coordsHalf2, 1, laneType,
180                     this.speedLimit, this.simulator)[0];
181             this.path.add(this.lane2);
182 
183             
184             double trackLength = this.lane1.getLength().getSI();
185             double variability = (headway - 20) * headwayVariability;
186             System.out.println("headway is " + headway + " variability limit is " + variability);
187             Random random = new Random(12345);
188             for (double pos = 0; pos <= trackLength - headway - variability;)
189             {
190                 
191                 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
192                 generateCar(this.lane1, new Length(pos, METER));
193                 pos += actualHeadway;
194             }
195             
196             trackLength = this.lane2.getLength().getSI();
197             variability = (headway - 20) * headwayVariability;
198             System.out.println("headway is " + headway + " variability limit is " + variability);
199             random = new Random(54321);
200             for (double pos = 0; pos <= trackLength - headway - variability;)
201             {
202                 
203                 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
204                 generateCar(this.lane2, new Length(pos, METER));
205                 pos += actualHeadway;
206             }
207 
208         }
209         catch (Exception exception)
210         {
211             exception.printStackTrace();
212         }
213     }
214 
215     
216 
217 
218 
219 
220 
221     protected final void generateCar(final Lane lane, final Length initialPosition) throws GTUException
222     {
223         
224         boolean generateTruck = this.stream.nextDouble() > this.carProbability;
225         Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
226         LaneBasedIndividualGTU gtu =
227                 new LaneBasedIndividualGTU("" + (++this.carsCreated), this.gtuType, vehicleLength, new Length(1.8, METER),
228                         new Speed(200, KM_PER_HOUR), vehicleLength.multiplyBy(0.5), this.simulator, this.network);
229         gtu.setParameters(generateTruck ? this.parametersTruck : this.parametersCar);
230         gtu.setNoLaneChangeDistance(Length.ZERO);
231         gtu.setMaximumAcceleration(Acceleration.createSI(3.0));
232         gtu.setMaximumDeceleration(Acceleration.createSI(-8.0));
233 
234         
235         LaneBasedStrategicalPlanner strategicalPlanner;
236         Route route = null;
237         if (!generateTruck)
238         {
239             strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu, route, null, null);
240         }
241         else
242         {
243             strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu, route, null, null);
244         }
245 
246         
247         Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
248         initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
249         Speed initialSpeed = new Speed(0, KM_PER_HOUR);
250         try
251         {
252             gtu.init(strategicalPlanner, initialPositions, initialSpeed);
253         }
254         catch (NetworkException | SimRuntimeException | OTSGeometryException exception)
255         {
256             throw new GTUException(exception);
257         }
258     }
259 
260     
261 
262 
263     public List<Lane> getPath()
264     {
265         return new ArrayList<>(this.path);
266     }
267 
268     
269     @Override
270     public OTSNetwork getNetwork()
271     {
272         return this.network;
273     }
274 
275     
276 
277 
278     public final Length getMinimumDistance()
279     {
280         return this.minimumDistance;
281     }
282 
283     
284 
285 
286 
287 
288     public void stopSimulator(final DEVSSimulatorInterface.TimeDoubleUnit theSimulator, final String errorMessage)
289     {
290         System.out.println("Error: " + errorMessage);
291         try
292         {
293             if (theSimulator.isRunning())
294             {
295                 theSimulator.stop();
296             }
297         }
298         catch (SimRuntimeException exception)
299         {
300             exception.printStackTrace();
301         }
302         throw new Error(errorMessage);
303     }
304 
305 }