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