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.draw.point.Point2d;
20 import org.djutils.traceverifier.TraceVerifier;
21 import org.opentrafficsim.base.parameters.Parameters;
22 import org.opentrafficsim.core.definitions.DefaultsNl;
23 import org.opentrafficsim.core.dsol.AbstractOtsModel;
24 import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
25 import org.opentrafficsim.core.geometry.OtsGeometryException;
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 Point2d(radius, 0), new Direction(90, DirectionUnit.EAST_DEGREE));
214 Node halfway =
215 new Node(this.network, "Halfway", new Point2d(-radius, 0), new Direction(270, DirectionUnit.EAST_DEGREE));
216
217 Point2d[] coordsHalf1 = new Point2d[127];
218 for (int i = 0; i < coordsHalf1.length; i++)
219 {
220 double angle = Math.PI * i / (coordsHalf1.length - 1);
221 coordsHalf1[i] = new Point2d(radius * Math.cos(angle), radius * Math.sin(angle));
222 }
223 Lane[] lanes1 = LaneFactory.makeMultiLane(this.network, "FirstHalf", start, halfway, coordsHalf1, laneCount,
224 laneType, this.speedLimit, this.simulator, DefaultsNl.VEHICLE);
225 Point2d[] coordsHalf2 = new Point2d[127];
226 for (int i = 0; i < coordsHalf2.length; i++)
227 {
228 double angle = Math.PI + Math.PI * i / (coordsHalf2.length - 1);
229 coordsHalf2[i] = new Point2d(radius * Math.cos(angle), radius * Math.sin(angle));
230 }
231 Lane[] lanes2 = LaneFactory.makeMultiLane(this.network, "SecondHalf", halfway, start, coordsHalf2, laneCount,
232 laneType, this.speedLimit, this.simulator, DefaultsNl.VEHICLE);
233 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
234 {
235 this.paths.get(laneIndex).add(lanes1[laneIndex]);
236 this.paths.get(laneIndex).add(lanes2[laneIndex]);
237 }
238
239 double variability = (headway - 20) * headwayVariability;
240 System.out.println("headway is " + headway + " variability limit is " + variability);
241 Random random = new Random(12345);
242 for (int laneIndex = 0; laneIndex < laneCount; laneIndex++)
243 {
244 double lane1Length = lanes1[laneIndex].getLength().getSI();
245 double trackLength = lane1Length + lanes2[laneIndex].getLength().getSI();
246 for (double pos = 0; pos <= trackLength - headway - variability;)
247 {
248 Lane lane = pos >= lane1Length ? lanes2[laneIndex] : lanes1[laneIndex];
249
250 double laneRelativePos = pos > lane1Length ? pos - lane1Length : pos;
251 double actualHeadway = headway + (random.nextDouble() * 2 - 1) * variability;
252
253 generateGTU(new Length(laneRelativePos, METER), lane, gtuType);
254 pos += actualHeadway;
255 }
256 }
257 }
258 catch (Exception exception)
259 {
260 exception.printStackTrace();
261 }
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275 protected final void generateGTU(final Length initialPosition, final Lane lane, final GtuType gtuType)
276 throws GtuException, NetworkException, SimRuntimeException, OtsGeometryException, InputParameterException
277 {
278
279 boolean generateTruck = this.stream.nextDouble() > this.carProbability;
280 Length vehicleLength = new Length(generateTruck ? 15 : 4, METER);
281 LaneBasedGtu gtu = new LaneBasedGtu("" + (++this.carsCreated), gtuType, vehicleLength, new Length(1.8, METER),
282 new Speed(200, KM_PER_HOUR), vehicleLength.times(0.5), this.network);
283 gtu.setParameters(generateTruck ? this.parametersTruck : this.parametersCar);
284 gtu.setNoLaneChangeDistance(Length.ZERO);
285 gtu.setInstantaneousLaneChange(!((boolean) getInputParameter("generic.gradualLaneChange")));
286 gtu.setMaximumAcceleration(Acceleration.instantiateSI(3.0));
287 gtu.setMaximumDeceleration(Acceleration.instantiateSI(-8.0));
288
289
290 LaneBasedStrategicalPlanner strategicalPlanner;
291 Route route = null;
292 if (!generateTruck)
293 {
294 strategicalPlanner = this.strategicalPlannerGeneratorCars.create(gtu, route, null, null);
295 }
296 else
297 {
298 strategicalPlanner = this.strategicalPlannerGeneratorTrucks.create(gtu, route, null, null);
299 }
300
301
302 Speed initialSpeed = new Speed(0, KM_PER_HOUR);
303 gtu.init(strategicalPlanner, new LanePosition(lane, initialPosition), initialSpeed);
304 }
305
306
307 @Override
308 public RoadNetwork getNetwork()
309 {
310 return this.network;
311 }
312
313
314
315
316 public final Length getMinimumDistance()
317 {
318 return this.minimumDistance;
319 }
320
321
322
323
324
325
326 public void stopSimulator(final OtsSimulatorInterface theSimulator, final String errorMessage)
327 {
328 System.out.println("Error: " + errorMessage);
329 try
330 {
331 if (theSimulator.isStartingOrRunning())
332 {
333 theSimulator.stop();
334 }
335 }
336 catch (SimRuntimeException exception)
337 {
338 exception.printStackTrace();
339 }
340 throw new Error(errorMessage);
341 }
342
343 }