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.LengthUnit;
10 import org.djunits.unit.UNITS;
11 import org.djunits.value.vdouble.scalar.Acceleration;
12 import org.djunits.value.vdouble.scalar.Length;
13 import org.djunits.value.vdouble.scalar.Speed;
14 import org.opentrafficsim.base.parameters.Parameters;
15 import org.opentrafficsim.core.dsol.AbstractOTSModel;
16 import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
17 import org.opentrafficsim.core.geometry.OTSGeometryException;
18 import org.opentrafficsim.core.geometry.OTSPoint3D;
19 import org.opentrafficsim.core.gtu.GTUDirectionality;
20 import org.opentrafficsim.core.gtu.GTUException;
21 import org.opentrafficsim.core.gtu.GTUType;
22 import org.opentrafficsim.core.network.NetworkException;
23 import org.opentrafficsim.core.network.OTSNode;
24 import org.opentrafficsim.core.network.route.Route;
25 import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU;
26 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
27 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
28 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
29 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner;
30 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
31 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
32 import org.opentrafficsim.road.network.OTSRoadNetwork;
33 import org.opentrafficsim.road.network.factory.LaneFactory;
34 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
35 import org.opentrafficsim.road.network.lane.Lane;
36 import org.opentrafficsim.road.network.lane.LaneType;
37
38 import nl.tudelft.simulation.dsol.SimRuntimeException;
39 import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDouble;
40 import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterDoubleScalar;
41 import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException;
42 import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterMap;
43 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
44 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
45 import nl.tudelft.simulation.jstats.streams.StreamInterface;
46
47
48
49
50
51
52
53
54
55
56
57 public class CircularLaneModel extends AbstractOTSModel implements UNITS
58 {
59
60 private static final long serialVersionUID = 20141121L;
61
62
63 private int carsCreated = 0;
64
65
66 private double carProbability;
67
68
69 private Length minimumDistance = new Length(0, METER);
70
71
72 private Speed speedLimit = new Speed(100, KM_PER_HOUR);
73
74
75 private List<Lane> path = new ArrayList<>();
76
77
78 private Lane lane1;
79
80
81 private Lane lane2;
82
83
84 private StreamInterface stream = new MersenneTwister(12345);
85
86
87 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorCars = null;
88
89
90 private LaneBasedStrategicalPlannerFactory<LaneBasedStrategicalPlanner> strategicalPlannerGeneratorTrucks = null;
91
92
93 private Parameters parametersCar;
94
95
96 private Parameters parametersTruck;
97
98
99 private final OTSRoadNetwork network = new OTSRoadNetwork("network", true);
100
101
102
103
104 public CircularLaneModel(final OTSSimulatorInterface simulator)
105 {
106 super(simulator);
107 makeInputParameterMap();
108 }
109
110
111
112
113 public void makeInputParameterMap()
114 {
115 try
116 {
117 InputParameterHelper.makeInputParameterMapCarTruck(this.inputParameterMap, 4.0);
118 InputParameterMap genericMap = (InputParameterMap) this.inputParameterMap.get("generic");
119
120 genericMap.add(new InputParameterDoubleScalar<LengthUnit, Length>("trackLength", "Track length",
121 "Track length (circumfence of the track)", Length.createSI(1000.0), Length.createSI(500.0),
122 Length.createSI(2000.0), true, true, "%.0f", 1.0));
123 genericMap.add(new InputParameterDouble("densityMean", "Mean density (veh / km)",
124 "mean density of the vehicles (vehicles per kilometer)", 30.0, 5.0, 45.0, true, true, "%.0f", 2.0));
125 genericMap.add(new InputParameterDouble("densityVariability", "Density variability",
126 "Variability of the denisty: variability * (headway - 20) meters", 0.0, 0.0, 1.0, true, true, "%.00f",
127 3.0));
128 }
129 catch (InputParameterException exception)
130 {
131 exception.printStackTrace();
132 }
133 }
134
135
136 @Override
137 public void constructModel() throws SimRuntimeException
138 {
139 try
140 {
141 this.carProbability = (double) getInputParameter("generic.carProbability");
142 double radius = ((Length) getInputParameter("generic.trackLength")).si / 2 / Math.PI;
143 double headway = 1000.0 / (double) getInputParameter("generic.densityMean");
144 double headwayVariability = (double) getInputParameter("generic.densityVariability");
145
146 this.parametersCar = InputParameterHelper.getParametersCar(getInputParameterMap());
147 this.parametersTruck = InputParameterHelper.getParametersTruck(getInputParameterMap());
148
149 this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(
150 new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
151 this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(
152 new LMRSFactory(new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory()));
153
154 LaneType laneType = this.network.getLaneType(LaneType.DEFAULTS.TWO_WAY_LANE);
155 OTSNode start = new OTSNode(this.network, "Start", new OTSPoint3D(radius, 0, 0));
156 OTSNode halfway = new OTSNode(this.network, "Halfway", new OTSPoint3D(-radius, 0, 0));
157
158 OTSPoint3D[] coordsHalf1 = new OTSPoint3D[127];
159 for (int i = 0; i < coordsHalf1.length; i++)
160 {
161 double angle = Math.PI * (1 + i) / (1 + coordsHalf1.length);
162 coordsHalf1[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
163 }
164 this.lane1 = LaneFactory.makeMultiLane(this.network, "Lane1", start, halfway, coordsHalf1, 1, laneType,
165 this.speedLimit, this.simulator)[0];
166 this.path.add(this.lane1);
167
168 OTSPoint3D[] coordsHalf2 = new OTSPoint3D[127];
169 for (int i = 0; i < coordsHalf2.length; i++)
170 {
171 double angle = Math.PI + Math.PI * (1 + i) / (1 + coordsHalf2.length);
172 coordsHalf2[i] = new OTSPoint3D(radius * Math.cos(angle), radius * Math.sin(angle), 0);
173 }
174 this.lane2 = LaneFactory.makeMultiLane(this.network, "Lane2", halfway, start, coordsHalf2, 1, laneType,
175 this.speedLimit, this.simulator)[0];
176 this.path.add(this.lane2);
177
178
179 double trackLength = this.lane1.getLength().getSI();
180 double variability = (headway - 20) * headwayVariability;
181 System.out.println("headway is " + headway + " variability limit is " + variability);
182 Random random = new Random(12345);
183 for (double pos = 0; pos <= trackLength - headway - variability;)
184 {
185
186 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
187 generateCar(this.lane1, new Length(pos, METER));
188 pos += actualHeadway;
189 }
190
191 trackLength = this.lane2.getLength().getSI();
192 variability = (headway - 20) * headwayVariability;
193 System.out.println("headway is " + headway + " variability limit is " + variability);
194 random = new Random(54321);
195 for (double pos = 0; pos <= trackLength - headway - variability;)
196 {
197
198 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
199 generateCar(this.lane2, new Length(pos, METER));
200 pos += actualHeadway;
201 }
202
203 }
204 catch (Exception exception)
205 {
206 exception.printStackTrace();
207 }
208 }
209
210
211
212
213
214
215
216 protected final void generateCar(final Lane lane, final Length initialPosition) throws GTUException
217 {
218
219 boolean generateTruck = this.stream.nextDouble() > this.carProbability;
220 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
221 LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated),
222 this.network.getGtuType(GTUType.DEFAULTS.CAR), vehicleLength, new Length(1.8, METER),
223 new Speed(200, KM_PER_HOUR), vehicleLength.multiplyBy(0.5), this.simulator, this.network);
224 gtu.setParameters(generateTruck ? this.parametersTruck : this.parametersCar);
225 gtu.setNoLaneChangeDistance(Length.ZERO);
226 gtu.setMaximumAcceleration(Acceleration.createSI(3.0));
227 gtu.setMaximumDeceleration(Acceleration.createSI(-8.0));
228
229
230 LaneBasedStrategicalPlanner strategicalPlanner;
231 Route route = null;
232 if (!generateTruck)
233 {
234 strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu, route, null, null);
235 }
236 else
237 {
238 strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu, route, null, null);
239 }
240
241
242 Set<DirectedLanePosition> initialPositions = new LinkedHashSet<>(1);
243 initialPositions.add(new DirectedLanePosition(lane, initialPosition, GTUDirectionality.DIR_PLUS));
244 Speed initialSpeed = new Speed(0, KM_PER_HOUR);
245 try
246 {
247 gtu.init(strategicalPlanner, initialPositions, initialSpeed);
248 }
249 catch (NetworkException | SimRuntimeException | OTSGeometryException exception)
250 {
251 throw new GTUException(exception);
252 }
253 }
254
255
256
257
258 public List<Lane> getPath()
259 {
260 return new ArrayList<>(this.path);
261 }
262
263
264 @Override
265 public OTSRoadNetwork getNetwork()
266 {
267 return this.network;
268 }
269
270
271
272
273 public final Length getMinimumDistance()
274 {
275 return this.minimumDistance;
276 }
277
278
279
280
281
282
283 public void stopSimulator(final DEVSSimulatorInterface.TimeDoubleUnit theSimulator, final String errorMessage)
284 {
285 System.out.println("Error: " + errorMessage);
286 try
287 {
288 if (theSimulator.isRunning())
289 {
290 theSimulator.stop();
291 }
292 }
293 catch (SimRuntimeException exception)
294 {
295 exception.printStackTrace();
296 }
297 throw new Error(errorMessage);
298 }
299
300 }