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 }