1   package org.opentrafficsim.web.test;
2   
3   import java.io.IOException;
4   import java.util.ArrayList;
5   import java.util.List;
6   import java.util.Random;
7   
8   import org.djunits.unit.DirectionUnit;
9   import org.djunits.unit.DurationUnit;
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.Duration;
15  import org.djunits.value.vdouble.scalar.Length;
16  import org.djunits.value.vdouble.scalar.Speed;
17  import org.djutils.draw.point.Point2d;
18  import org.djutils.traceverifier.TraceVerifier;
19  import org.opentrafficsim.base.parameters.Parameters;
20  import org.opentrafficsim.core.definitions.DefaultsNl;
21  import org.opentrafficsim.core.dsol.AbstractOtsModel;
22  import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
23  import org.opentrafficsim.core.gtu.Gtu;
24  import org.opentrafficsim.core.gtu.GtuException;
25  import org.opentrafficsim.core.gtu.GtuType;
26  import org.opentrafficsim.core.network.NetworkException;
27  import org.opentrafficsim.core.network.Node;
28  import org.opentrafficsim.core.network.route.Route;
29  import org.opentrafficsim.road.definitions.DefaultsRoadNl;
30  import org.opentrafficsim.road.gtu.lane.LaneBasedGtu;
31  import org.opentrafficsim.road.gtu.lane.tactical.following.IdmPlusFactory;
32  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLmrsPerceptionFactory;
33  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LmrsFactory;
34  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
35  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
36  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalRoutePlannerFactory;
37  import org.opentrafficsim.road.network.RoadNetwork;
38  import org.opentrafficsim.road.network.factory.LaneFactory;
39  import org.opentrafficsim.road.network.lane.Lane;
40  import org.opentrafficsim.road.network.lane.LanePosition;
41  import org.opentrafficsim.road.network.lane.LaneType;
42  
43  import nl.tudelft.simulation.dsol.SimRuntimeException;
44  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterBoolean;
45  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDouble;
46  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDoubleScalar;
47  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException;
48  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterMap;
49  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
50  import nl.tudelft.simulation.jstats.streams.StreamInterface;
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<?> strategicalPlannerGeneratorCars = null;
85  
86      
87      private LaneBasedStrategicalPlannerFactory<?> strategicalPlannerGeneratorTrucks = null;
88  
89      
90      private Parameters parametersCar;
91  
92      
93      private Parameters parametersTruck;
94  
95      
96      private final RoadNetwork network;
97  
98      
99  
100 
101     public CircularRoadModel(final OtsSimulatorInterface simulator)
102     {
103         super(simulator);
104         this.network = new RoadNetwork("network", simulator);
105         makeInputParameterMap();
106     }
107 
108     
109 
110 
111     public void makeInputParameterMap()
112     {
113         try
114         {
115             InputParameterHelper.makeInputParameterMapCarTruck(this.inputParameterMap, 1.0);
116 
117             InputParameterMap genericMap = null;
118             if (this.inputParameterMap.getValue().containsKey("generic"))
119             {
120                 genericMap = (InputParameterMap) this.inputParameterMap.get("generic");
121             }
122             else
123             {
124                 genericMap = new InputParameterMap("generic", "Generic", "Generic parameters", 1.0);
125                 this.inputParameterMap.add(genericMap);
126             }
127 
128             genericMap.add(new InputParameterDoubleScalar<LengthUnit, Length>("trackLength", "Track length",
129                     "Track length (circumfence of the track)", Length.instantiateSI(1000.0), Length.instantiateSI(500.0),
130                     Length.instantiateSI(2000.0), true, true, "%.0f", 1.5));
131             genericMap.add(new InputParameterDouble("densityMean", "Mean density (veh / km)",
132                     "mean density of the vehicles (vehicles per kilometer)", 30.0, 5.0, 45.0, true, true, "%.0f", 2.0));
133             genericMap.add(new InputParameterDouble("densityVariability", "Density variability",
134                     "Variability of the denisty: variability * (headway - 20) meters", 0.0, 0.0, 1.0, true, true, "%.00f",
135                     3.0));
136             genericMap.add(new InputParameterBoolean("gradualLaneChange", "Gradual lane change",
137                     "Gradual lane change when true; instantaneous lane change when false", true, 4.0));
138         }
139         catch (InputParameterException exception)
140         {
141             exception.printStackTrace();
142         }
143     }
144 
145     
146 
147 
148 
149     public List<Lane> getPath(final int index)
150     {
151         return this.paths.get(index);
152     }
153 
154     
155 
156 
157 
158     public void sample(final TraceVerifier tv)
159     {
160         try
161         {
162             StringBuilder state = new StringBuilder();
163             for (Gtu gtu : this.network.getGTUs())
164             {
165                 LaneBasedGtu lbg = (LaneBasedGtu) gtu;
166                 state.append(String.format("%s: %130.130s ", lbg.getId(), lbg.getLocation().toString()));
167             }
168 
169             tv.sample(this.simulator.getSimulatorTime().toString(), state.toString());
170             this.simulator.scheduleEventRel(new Duration(1, DurationUnit.SECOND), this, "sample", new Object[] {tv});
171         }
172         catch (IOException e)
173         {
174             e.printStackTrace();
175         }
176     }
177 
178     @Override
179     public void constructModel() throws SimRuntimeException
180     {
181         try
182         {
183             
184             
185             
186             
187             
188             final int laneCount = 2;
189             for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
190             {
191                 this.paths.add(new ArrayList<Lane>());
192             }
193 
194             this.carProbability = (double) getInputParameter("generic.carProbability");
195             double radius = ((Length) getInputParameter("generic.trackLength")).si / 2 / Math.PI;
196             double headway = 1000.0 / (double) getInputParameter("generic.densityMean");
197             double headwayVariability = (double) getInputParameter("generic.densityVariability");
198 
199             this.parametersCar = InputParameterHelper.getParametersCar(getInputParameterMap());
200             this.parametersTruck = InputParameterHelper.getParametersTruck(getInputParameterMap());
201 
202             this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
203                     new LmrsFactory(new IdmPlusFactory(this.stream), new DefaultLmrsPerceptionFactory()));
204             this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
205                     new LmrsFactory(new IdmPlusFactory(this.stream), new DefaultLmrsPerceptionFactory()));
206 
207             GtuType gtuType = DefaultsNl.CAR;
208             LaneType laneType = DefaultsRoadNl.TWO_WAY_LANE;
209             Node start = new Node(this.network, "Start", new Point2d(radius, 0), new Direction(90, DirectionUnit.EAST_DEGREE));
210             Node halfway =
211                     new Node(this.network, "Halfway", new Point2d(-radius, 0), new Direction(270, DirectionUnit.EAST_DEGREE));
212 
213             Point2d[] coordsHalf1 = new Point2d[127];
214             for (int i = 0; i < coordsHalf1.length; i++)
215             {
216                 double angle = Math.PI * i / (coordsHalf1.length - 1);
217                 coordsHalf1[i] = new Point2d(radius * Math.cos(angle), radius * Math.sin(angle));
218             }
219             Lane[] lanes1 = LaneFactory.makeMultiLane(this.network, "FirstHalf", start, halfway, coordsHalf1, laneCount,
220                     laneType, this.speedLimit, this.simulator, DefaultsNl.VEHICLE);
221             Point2d[] coordsHalf2 = new Point2d[127];
222             for (int i = 0; i < coordsHalf2.length; i++)
223             {
224                 double angle = Math.PI + Math.PI * i / (coordsHalf2.length - 1);
225                 coordsHalf2[i] = new Point2d(radius * Math.cos(angle), radius * Math.sin(angle));
226             }
227             Lane[] lanes2 = LaneFactory.makeMultiLane(this.network, "SecondHalf", halfway, start, coordsHalf2, laneCount,
228                     laneType, this.speedLimit, this.simulator, DefaultsNl.VEHICLE);
229             for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
230             {
231                 this.paths.get(laneIndex).add(lanes1[laneIndex]);
232                 this.paths.get(laneIndex).add(lanes2[laneIndex]);
233             }
234             
235             double variability = (headway - 20) * headwayVariability;
236             System.out.println("headway is " + headway + " variability limit is " + variability);
237             Random random = new Random(12345);
238             for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
239             {
240                 double lane1Length = lanes1[laneIndex].getLength().getSI();
241                 double trackLength = lane1Length + lanes2[laneIndex].getLength().getSI();
242                 for (double pos = 0; pos <= trackLength - headway - variability;)
243                 {
244                     Lane lane = pos >= lane1Length ? lanes2[laneIndex] : lanes1[laneIndex];
245                     
246                     double laneRelativePos = pos > lane1Length ? pos - lane1Length : pos;
247                     double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
248                     
249                     generateGTU(new Length(laneRelativePos, METER), lane, gtuType);
250                     pos += actualHeadway;
251                 }
252             }
253         }
254         catch (Exception exception)
255         {
256             exception.printStackTrace();
257         }
258     }
259 
260     
261 
262 
263 
264 
265 
266 
267 
268 
269 
270     protected final void generateGTU(final Length initialPosition, final Lane lane, final GtuType gtuType)
271             throws GtuException, NetworkException, SimRuntimeException, InputParameterException
272     {
273         
274         boolean generateTruck = this.stream.nextDouble() > this.carProbability;
275         Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
276         LaneBasedGtu gtu = new LaneBasedGtu("" + (++this.carsCreated), gtuType, vehicleLength, new Length(1.8, METER),
277                 new Speed(200, KM_PER_HOUR), vehicleLength.times(0.5), this.network);
278         gtu.setParameters(generateTruck ? this.parametersTruck : this.parametersCar);
279         gtu.setNoLaneChangeDistance(Length.ZERO);
280         gtu.setInstantaneousLaneChange(!((boolean) getInputParameter("generic.gradualLaneChange")));
281         gtu.setMaximumAcceleration(Acceleration.instantiateSI(3.0));
282         gtu.setMaximumDeceleration(Acceleration.instantiateSI(-8.0));
283 
284         
285         LaneBasedStrategicalPlanner strategicalPlanner;
286         Route route = null;
287         if (!generateTruck)
288         {
289             strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu, route, null, null);
290         }
291         else
292         {
293             strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu, route, null, null);
294         }
295 
296         
297         Speed initialSpeed = new Speed(0, KM_PER_HOUR);
298         gtu.init(strategicalPlanner, new LanePosition(lane, initialPosition), initialSpeed);
299     }
300 
301     @Override
302     public RoadNetwork getNetwork()
303     {
304         return this.network;
305     }
306 
307     
308 
309 
310     public final Length getMinimumDistance()
311     {
312         return this.minimumDistance;
313     }
314 
315     
316 
317 
318 
319 
320     public void stopSimulator(final OtsSimulatorInterface theSimulator, final String errorMessage)
321     {
322         System.out.println("Error: " + errorMessage);
323         try
324         {
325             if (theSimulator.isStartingOrRunning())
326             {
327                 theSimulator.stop();
328             }
329         }
330         catch (SimRuntimeException exception)
331         {
332             exception.printStackTrace();
333         }
334         throw new Error(errorMessage);
335     }
336 
337 }