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 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 OTSNetwork network = new OTSNetwork("network");
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.createSI(1000.0), Length.createSI(500.0),
128                     Length.createSI(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         try
155         {
156             final int laneCount = 2;
157             for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
158             {
159                 this.paths.add(new ArrayList<Lane>());
160             }
161 
162             this.carProbability = (double) getInputParameter("generic.carProbability");
163             double radius = ((Length) getInputParameter("generic.trackLength")).si / 2 / Math.PI;
164             double headway = 1000.0 / (double) getInputParameter("generic.densityMean");
165             double headwayVariability = (double) getInputParameter("generic.densityVariability");
166 
167             this.parametersCar = InputParameterHelper.getParametersCar(getInputParameterMap());
168             this.parametersTruck = InputParameterHelper.getParametersTruck(getInputParameterMap());
169 
170             this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
171                     new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
172             this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
173                     new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
174 
175             GTUType gtuType = CAR;
176             LaneType laneType = LaneType.TWO_WAY_LANE;
177             OTSNode start = new OTSNode(this.network, "Start", new OTSPoint3D(radius, 0, 0));
178             OTSNode halfway = new OTSNode(this.network, "Halfway", new OTSPoint3D(-radius, 0, 0));
179 
180             OTSPoint3D[] coordsHalf1 = new OTSPoint3D[127];
181             for (int i = 0; i < coordsHalf1.length; i++)
182             {
183                 double angle = Math.PI * (1 + i) / (1 + coordsHalf1.length);
184                 coordsHalf1[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
185             }
186             Lane[] lanes1 = LaneFactory.makeMultiLane(this.network, "FirstHalf", start, halfway, coordsHalf1, laneCount,
187                     laneType, this.speedLimit, this.simulator);
188             OTSPoint3D[] coordsHalf2 = new OTSPoint3D[127];
189             for (int i = 0; i < coordsHalf2.length; i++)
190             {
191                 double angle = Math.PI + Math.PI * (1 + i) / (1 + coordsHalf2.length);
192                 coordsHalf2[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
193             }
194             Lane[] lanes2 = LaneFactory.makeMultiLane(this.network, "SecondHalf", halfway, start, coordsHalf2, laneCount,
195                     laneType, this.speedLimit, this.simulator);
196             for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
197             {
198                 this.paths.get(laneIndex).add(lanes1[laneIndex]);
199                 this.paths.get(laneIndex).add(lanes2[laneIndex]);
200             }
201             
202             double variability = (headway - 20) * headwayVariability;
203             System.out.println("headway is " + headway + " variability limit is " + variability);
204             Random random = new Random(12345);
205             for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
206             {
207                 double lane1Length = lanes1[laneIndex].getLength().getSI();
208                 double trackLength = lane1Length + lanes2[laneIndex].getLength().getSI();
209                 for (double pos = 0; pos <= trackLength - headway - variability;)
210                 {
211                     Lane lane = pos >= lane1Length ? lanes2[laneIndex] : lanes1[laneIndex];
212                     
213                     double laneRelativePos = pos > lane1Length ? pos - lane1Length : pos;
214                     double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
215                     
216                     generateGTU(new Length(laneRelativePos, METER), lane, gtuType);
217                     pos += actualHeadway;
218                 }
219             }
220 
221         }
222         catch (Exception exception)
223         {
224             exception.printStackTrace();
225         }
226     }
227 
228     
229 
230 
231 
232 
233 
234 
235 
236 
237 
238     protected final void generateGTU(final Length initialPosition, final Lane lane, final GTUType gtuType)
239             throws GTUException, NetworkException, SimRuntimeException, OTSGeometryException
240     {
241         
242         boolean generateTruck = this.stream.nextDouble() > this.carProbability;
243         Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
244         LaneBasedIndividualGTU gtu =
245                 new LaneBasedIndividualGTU("" + (++this.carsCreated), gtuType, vehicleLength, new Length(1.8, METER),
246                         new Speed(200, KM_PER_HOUR), vehicleLength.multiplyBy(0.5), this.simulator, this.network);
247         gtu.setParameters(generateTruck ? this.parametersTruck : this.parametersCar);
248         gtu.setNoLaneChangeDistance(Length.ZERO);
249         gtu.setMaximumAcceleration(Acceleration.createSI(3.0));
250         gtu.setMaximumDeceleration(Acceleration.createSI(-8.0));
251 
252         
253         LaneBasedStrategicalPlanner strategicalPlanner;
254         Route route = null;
255         if (!generateTruck)
256         {
257             strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu, route, null, null);
258         }
259         else
260         {
261             strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu, route, null, null);
262         }
263 
264         
265         Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
266         initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
267         Speed initialSpeed = new Speed(0, KM_PER_HOUR);
268         gtu.init(strategicalPlanner, initialPositions, initialSpeed);
269     }
270 
271     
272     @Override
273     public OTSNetwork getNetwork()
274     {
275         return this.network;
276     }
277 
278     
279 
280 
281     public final Length getMinimumDistance()
282     {
283         return this.minimumDistance;
284     }
285 
286     
287 
288 
289 
290 
291     public void stopSimulator(final DEVSSimulatorInterface.TimeDoubleUnit theSimulator, final String errorMessage)
292     {
293         System.out.println("Error: " + errorMessage);
294         try
295         {
296             if (theSimulator.isRunning())
297             {
298                 theSimulator.stop();
299             }
300         }
301         catch (SimRuntimeException exception)
302         {
303             exception.printStackTrace();
304         }
305         throw new Error(errorMessage);
306     }
307 
308 }