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