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