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