1 package org.opentrafficsim.demo;
2
3 import java.io.Serializable;
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.LengthUnit;
12 import org.djunits.unit.util.UNITS;
13 import org.djunits.value.vdouble.scalar.Acceleration;
14 import org.djunits.value.vdouble.scalar.Direction;
15 import org.djunits.value.vdouble.scalar.Length;
16 import org.djunits.value.vdouble.scalar.Speed;
17 import org.opentrafficsim.base.parameters.Parameters;
18 import org.opentrafficsim.core.dsol.AbstractOTSModel;
19 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
20 import org.opentrafficsim.core.geometry.OTSGeometryException;
21 import org.opentrafficsim.core.geometry.OTSPoint3D;
22 import org.opentrafficsim.core.gtu.GTUDirectionality;
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.route.Route;
27 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
28 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
29 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
30 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
31 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
32 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
33 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
34 import org.opentrafficsim.road.network.OTSRoadNetwork;
35 import org.opentrafficsim.road.network.factory.LaneFactory;
36 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
37 import org.opentrafficsim.road.network.lane.Lane;
38 import org.opentrafficsim.road.network.lane.LaneType;
39 import org.opentrafficsim.road.network.lane.OTSRoadNode;
40
41 import nl.tudelft.simulation.dsol.SimRuntimeException;
42 import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterBoolean;
43 import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDouble;
44 import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDoubleScalar;
45 import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException;
46 import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterMap;
47 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
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
60
61 public class CircularRoadModel extends AbstractOTSModel implements UNITS
62 {
63
64 private static final long serialVersionUID = 20141121L;
65
66
67 private int carsCreated = 0;
68
69
70 private double carProbability;
71
72
73 private Length minimumDistance = new Length(0, METER);
74
75
76 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
77
78
79 private List<List<Lane>> paths = new ArrayList<>();
80
81
82 private StreamInterface stream = new MersenneTwister(12345);
83
84
85 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
86
87
88 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
89
90
91 private Parameters parametersCar;
92
93
94 private Parameters parametersTruck;
95
96
97 private final OTSRoadNetwork network = new OTSRoadNetwork("network", true);
98
99
100
101
102 public CircularRoadModel(final OTSSimulatorInterface simulator)
103 {
104 super(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 @Override
156 public void constructModel() throws SimRuntimeException
157 {
158 try
159 {
160 final int laneCount = 2;
161 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
162 {
163 this.paths.add(new ArrayList<Lane>());
164 }
165
166 this.carProbability = (double) getInputParameter("generic.carProbability");
167 double radius = ((Length) getInputParameter("generic.trackLength")).si / 2 / Math.PI;
168 double headway = 1000.0 / (double) getInputParameter("generic.densityMean");
169 double headwayVariability = (double) getInputParameter("generic.densityVariability");
170
171 this.parametersCar = InputParameterHelper.getParametersCar(getInputParameterMap());
172 this.parametersTruck = InputParameterHelper.getParametersTruck(getInputParameterMap());
173
174 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
175 new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
176 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
177 new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
178
179 GTUType gtuType = this.network.getGtuType(GTUType.DEFAULTS.CAR);
180 LaneType laneType = this.network.getLaneType(LaneType.DEFAULTS.TWO_WAY_LANE);
181 OTSRoadNode start = new OTSRoadNode(this.network, "Start", new OTSPoint3D(radius, 0, 0),
182 new Direction(90, DirectionUnit.EAST_DEGREE));
183 OTSRoadNode halfway = new OTSRoadNode(this.network, "Halfway", new OTSPoint3D(-radius, 0, 0),
184 new Direction(270, DirectionUnit.EAST_DEGREE));
185
186 OTSPoint3D[] coordsHalf1 = new OTSPoint3D[127];
187 for (int i = 0; i < coordsHalf1.length; i++)
188 {
189 double angle = Math.PI * (1 + i) / (1 + coordsHalf1.length);
190 coordsHalf1[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
191 }
192 Lane[] lanes1 = LaneFactory.makeMultiLane(this.network, "FirstHalf", start, halfway, coordsHalf1, laneCount,
193 laneType, this.speedLimit, this.simulator);
194 OTSPoint3D[] coordsHalf2 = new OTSPoint3D[127];
195 for (int i = 0; i < coordsHalf2.length; i++)
196 {
197 double angle = Math.PI + Math.PI * (1 + i) / (1 + coordsHalf2.length);
198 coordsHalf2[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
199 }
200 Lane[] lanes2 = LaneFactory.makeMultiLane(this.network, "SecondHalf", halfway, start, coordsHalf2, laneCount,
201 laneType, this.speedLimit, this.simulator);
202 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
203 {
204 this.paths.get(laneIndex).add(lanes1[laneIndex]);
205 this.paths.get(laneIndex).add(lanes2[laneIndex]);
206 }
207
208 double variability = (headway - 20) * headwayVariability;
209 System.out.println("headway is " + headway + " variability limit is " + variability);
210 Random random = new Random(12345);
211 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
212 {
213 double lane1Length = lanes1[laneIndex].getLength().getSI();
214 double trackLength = lane1Length + lanes2[laneIndex].getLength().getSI();
215 for (double pos = 0; pos <= trackLength - headway - variability;)
216 {
217 Lane lane = pos >= lane1Length ? lanes2[laneIndex] : lanes1[laneIndex];
218
219 double laneRelativePos = pos > lane1Length ? pos - lane1Length : pos;
220 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
221
222 generateGTU(new Length(laneRelativePos, METER), lane, gtuType);
223 pos += actualHeadway;
224 }
225 }
226
227 }
228 catch (Exception exception)
229 {
230 exception.printStackTrace();
231 }
232 }
233
234
235
236
237
238
239
240
241
242
243
244
245 protected final void generateGTU(final Length initialPosition, final Lane lane, final GTUType gtuType)
246 throws GTUException, NetworkException, SimRuntimeException, OTSGeometryException, InputParameterException
247 {
248
249 boolean generateTruck = this.stream.nextDouble() > this.carProbability;
250 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
251 LaneBasedIndividualGTU gtu =
252 new LaneBasedIndividualGTU("" + (++this.carsCreated), gtuType, vehicleLength, new Length(1.8, METER),
253 new Speed(200, KM_PER_HOUR), vehicleLength.times(0.5), this.simulator, this.network);
254 gtu.setParameters(generateTruck ? this.parametersTruck : this.parametersCar);
255 gtu.setNoLaneChangeDistance(Length.ZERO);
256 gtu.setInstantaneousLaneChange(!((boolean) getInputParameter("generic.gradualLaneChange")));
257 gtu.setMaximumAcceleration(Acceleration.instantiateSI(3.0));
258 gtu.setMaximumDeceleration(Acceleration.instantiateSI(-8.0));
259
260
261 LaneBasedStrategicalPlanner strategicalPlanner;
262 Route route = null;
263 if (!generateTruck)
264 {
265 strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu, route, null, null);
266 }
267 else
268 {
269 strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu, route, null, null);
270 }
271
272
273 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
274 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
275 Speed initialSpeed = new Speed(0, KM_PER_HOUR);
276 gtu.init(strategicalPlanner, initialPositions, initialSpeed);
277 }
278
279
280 @Override
281 public OTSRoadNetwork getNetwork()
282 {
283 return this.network;
284 }
285
286
287
288
289 public final Length getMinimumDistance()
290 {
291 return this.minimumDistance;
292 }
293
294
295
296
297
298
299 public void stopSimulator(final DEVSSimulatorInterface.TimeDoubleUnit theSimulator, final String errorMessage)
300 {
301 System.out.println("Error: " + errorMessage);
302 try
303 {
304 if (theSimulator.isRunning())
305 {
306 theSimulator.stop();
307 }
308 }
309 catch (SimRuntimeException exception)
310 {
311 exception.printStackTrace();
312 }
313 throw new Error(errorMessage);
314 }
315
316
317 @Override
318 public Serializable getSourceId()
319 {
320 return "CircularRoadModel";
321 }
322
323 }