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