View Javadoc
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.Map;
7   import java.util.Set;
8   
9   import org.djunits.unit.DurationUnit;
10  import org.djunits.unit.LengthUnit;
11  import org.djunits.unit.SpeedUnit;
12  import org.djunits.unit.TimeUnit;
13  import org.djunits.unit.util.UNITS;
14  import org.djunits.value.vdouble.scalar.Direction;
15  import org.djunits.value.vdouble.scalar.Duration;
16  import org.djunits.value.vdouble.scalar.Frequency;
17  import org.djunits.value.vdouble.scalar.Length;
18  import org.djunits.value.vdouble.scalar.Speed;
19  import org.djunits.value.vdouble.scalar.Time;
20  import org.opentrafficsim.base.parameters.ParameterException;
21  import org.opentrafficsim.base.parameters.ParameterSet;
22  import org.opentrafficsim.core.definitions.DefaultsNl;
23  import org.opentrafficsim.core.distributions.ConstantGenerator;
24  import org.opentrafficsim.core.distributions.Distribution;
25  import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
26  import org.opentrafficsim.core.distributions.Generator;
27  import org.opentrafficsim.core.distributions.ProbabilityException;
28  import org.opentrafficsim.core.dsol.AbstractOtsModel;
29  import org.opentrafficsim.core.dsol.OtsSimulatorInterface;
30  import org.opentrafficsim.core.geometry.OtsGeometryException;
31  import org.opentrafficsim.core.geometry.OtsPoint3d;
32  import org.opentrafficsim.core.gtu.GtuType;
33  import org.opentrafficsim.core.idgenerator.IdGenerator;
34  import org.opentrafficsim.core.network.NetworkException;
35  import org.opentrafficsim.core.network.Node;
36  import org.opentrafficsim.core.network.route.FixedRouteGenerator;
37  import org.opentrafficsim.core.network.route.Route;
38  import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
39  import org.opentrafficsim.road.definitions.DefaultsRoadNl;
40  import org.opentrafficsim.road.gtu.generator.GeneratorPositions;
41  import org.opentrafficsim.road.gtu.generator.LaneBasedGtuGenerator;
42  import org.opentrafficsim.road.gtu.generator.TtcRoomChecker;
43  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedGtuTemplate;
44  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedGtuTemplateDistribution;
45  import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIdm;
46  import org.opentrafficsim.road.gtu.lane.tactical.following.IdmPlusFactory;
47  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLmrsPerceptionFactory;
48  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LmrsFactory;
49  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
50  import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalRoutePlannerFactory;
51  import org.opentrafficsim.road.network.RoadNetwork;
52  import org.opentrafficsim.road.network.factory.LaneFactory;
53  import org.opentrafficsim.road.network.lane.CrossSectionLink;
54  import org.opentrafficsim.road.network.lane.Lane;
55  import org.opentrafficsim.road.network.lane.LanePosition;
56  import org.opentrafficsim.road.network.lane.LaneType;
57  import org.opentrafficsim.road.network.lane.object.detector.SinkDetector;
58  import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLight;
59  import org.opentrafficsim.road.network.lane.object.trafficlight.TrafficLightColor;
60  
61  import nl.tudelft.simulation.dsol.SimRuntimeException;
62  import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException;
63  import nl.tudelft.simulation.jstats.distributions.DistUniform;
64  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
65  import nl.tudelft.simulation.jstats.streams.StreamInterface;
66  
67  /**
68   * Simulate a single lane road of 5 km length. Vehicles are generated at a constant rate of 1500 veh/hour. At time 300s a
69   * blockade is inserted at position 4 km; this blockade is removed at time 500s. The used car following algorithm is IDM+
70   * <a href="http://opentrafficsim.org/downloads/MOTUS%20reference.pdf"><i>Integrated Lane Change Model with Relaxation and
71   * Synchronization</i>, by Wouter J. Schakel, Victor L. Knoop and Bart van Arem, 2012</a>. <br>
72   * Output is a set of block charts:
73   * <ul>
74   * <li>Traffic density</li>
75   * <li>Speed</li>
76   * <li>Flow</li>
77   * <li>Acceleration</li>
78   * </ul>
79   * All these graphs display simulation time along the horizontal axis and distance along the road along the vertical axis.
80   * <p>
81   * Copyright (c) 2013-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
82   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
83   * </p>
84   * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
85   */
86  public class StraightModel extends AbstractOtsModel implements UNITS
87  {
88      /** */
89      private static final long serialVersionUID = 20140815L;
90  
91      /** The network. */
92      private final RoadNetwork network = new RoadNetwork("network", getSimulator());
93  
94      /** The probability that the next generated GTU is a passenger car. */
95      private double carProbability;
96  
97      /** The blocking, implemented as a traffic light. */
98      private TrafficLight block = null;
99  
100     /** Maximum distance. */
101     private Length maximumDistance = new Length(5000, METER);
102 
103     /** The Lane that contains the simulated Cars. */
104     private Lane lane;
105 
106     /** The random number generator used to decide what kind of GTU to generate. */
107     private StreamInterface stream = new MersenneTwister(12345);
108 
109     /** The sequence of Lanes that all vehicles will follow. */
110     private List<Lane> path = new ArrayList<>();
111 
112     /** The speed limit on all Lanes. */
113     private Speed speedLimit = new Speed(120, KM_PER_HOUR);
114 
115     /**
116      * @param simulator OtsSimulatorInterface; the simulator for this model
117      */
118     public StraightModel(final OtsSimulatorInterface simulator)
119     {
120         super(simulator);
121         InputParameterHelper.makeInputParameterMapCarTruck(this.inputParameterMap, 1.0);
122     }
123 
124     /** {@inheritDoc} */
125     @Override
126     public final void constructModel() throws SimRuntimeException
127     {
128         try
129         {
130             Node from = new Node(this.network, "From", new OtsPoint3d(0.0, 0, 0), Direction.ZERO);
131             Node to =
132                     new Node(this.network, "To", new OtsPoint3d(this.maximumDistance.getSI(), 0, 0), Direction.ZERO);
133             Node end = new Node(this.network, "End", new OtsPoint3d(this.maximumDistance.getSI() + 50.0, 0, 0),
134                     Direction.ZERO);
135             LaneType laneType = DefaultsRoadNl.TWO_WAY_LANE;
136             this.lane = LaneFactory.makeLane(this.network, "Lane", from, to, null, laneType, this.speedLimit, this.simulator,
137                     DefaultsNl.VEHICLE);
138             this.path.add(this.lane);
139             CrossSectionLink endLink = LaneFactory.makeLink(this.network, "endLink", to, end, null, this.simulator);
140             // No overtaking, single lane
141             Lane sinkLane = new Lane(endLink, "sinkLane", this.lane.getLateralCenterPosition(1.0),
142                     this.lane.getLateralCenterPosition(1.0), this.lane.getWidth(1.0), this.lane.getWidth(1.0), laneType,
143                     Map.of(DefaultsNl.VEHICLE, this.speedLimit), false);
144             new SinkDetector(sinkLane, new Length(10.0, METER), this.simulator, DefaultsRoadNl.ROAD_USERS);
145             this.path.add(sinkLane);
146 
147             this.carProbability = (double) getInputParameter("generic.carProbability");
148 
149             // Generation of a new car / truck
150             TtcRoomChecker roomChecker = new TtcRoomChecker(new Duration(10.0, DurationUnit.SI));
151             IdGenerator idGenerator = new IdGenerator("");
152             ParameterSet params = new ParameterSet();
153             params.setDefaultParameter(AbstractIdm.DELTA);
154             GtuType car = DefaultsNl.CAR;
155             GtuType truck = DefaultsNl.TRUCK;
156             ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedCar =
157                     new ContinuousDistDoubleScalar.Rel<>(new DistUniform(this.stream, 90.0, 110.0), SpeedUnit.KM_PER_HOUR);
158             ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedTruck =
159                     new ContinuousDistDoubleScalar.Rel<>(new DistUniform(this.stream, 80, 95), SpeedUnit.KM_PER_HOUR);
160             Generator<Route> routeGenerator = new FixedRouteGenerator(null);
161             LaneBasedStrategicalPlannerFactory<?> strategicalPlannerFactoryCars = new LaneBasedStrategicalRoutePlannerFactory(
162                     new LmrsFactory(new IdmPlusFactory(this.stream), new DefaultLmrsPerceptionFactory()));
163             LaneBasedStrategicalPlannerFactory<?> strategicalPlannerFctoryTrucks = new LaneBasedStrategicalRoutePlannerFactory(
164                     new LmrsFactory(new IdmPlusFactory(this.stream), new DefaultLmrsPerceptionFactory()));
165             LaneBasedGtuTemplate carTemplate = new LaneBasedGtuTemplate(car, new ConstantGenerator<>(Length.instantiateSI(4.0)),
166                     new ConstantGenerator<>(Length.instantiateSI(2.0)), speedCar, strategicalPlannerFactoryCars,
167                     routeGenerator);
168             LaneBasedGtuTemplate truckTemplate = new LaneBasedGtuTemplate(truck,
169                     new ConstantGenerator<>(Length.instantiateSI(15.0)), new ConstantGenerator<>(Length.instantiateSI(2.5)),
170                     speedTruck, strategicalPlannerFctoryTrucks, routeGenerator);
171             Distribution<LaneBasedGtuTemplate> gtuTypeDistribution = new Distribution<>(this.stream);
172             gtuTypeDistribution.add(new FrequencyAndObject<>(this.carProbability, carTemplate));
173             gtuTypeDistribution.add(new FrequencyAndObject<>(1.0 - this.carProbability, truckTemplate));
174             Generator<Duration> headwayGenerator = new HeadwayGenerator(new Frequency(1500.0, PER_HOUR));
175             Set<LanePosition> initialLongitudinalPositions = new LinkedHashSet<>();
176             initialLongitudinalPositions.add(new LanePosition(this.lane, new Length(5.0, LengthUnit.SI)));
177             LaneBasedGtuTemplateDistribution characteristicsGenerator =
178                     new LaneBasedGtuTemplateDistribution(gtuTypeDistribution);
179             new LaneBasedGtuGenerator("Generator", headwayGenerator, characteristicsGenerator,
180                     GeneratorPositions.create(initialLongitudinalPositions, this.stream), this.network, getSimulator(),
181                     roomChecker, idGenerator);
182             // End generation
183 
184             this.block = new TrafficLight(this.lane.getId() + "_TL", this.lane,
185                     new Length(new Length(4000.0, LengthUnit.METER)), this.simulator);
186             this.block.setTrafficLightColor(TrafficLightColor.GREEN);
187             // Create a block at t = 5 minutes
188             this.simulator.scheduleEventAbsTime(new Time(300, TimeUnit.BASE_SECOND), this, "createBlock", null);
189             // Remove the block at t = 7 minutes
190             this.simulator.scheduleEventAbsTime(new Time(420, TimeUnit.BASE_SECOND), this, "removeBlock", null);
191         }
192         catch (SimRuntimeException | NetworkException | OtsGeometryException | InputParameterException | ParameterException
193                 | ProbabilityException exception)
194         {
195             exception.printStackTrace();
196         }
197     }
198 
199     /**
200      * Set up the block.
201      */
202     protected final void createBlock()
203     {
204         this.block.setTrafficLightColor(TrafficLightColor.RED);
205     }
206 
207     /**
208      * Remove the block.
209      */
210     protected final void removeBlock()
211     {
212         this.block.setTrafficLightColor(TrafficLightColor.GREEN);
213     }
214 
215     /** {@inheritDoc} */
216     @Override
217     public RoadNetwork getNetwork()
218     {
219         return this.network;
220     }
221 
222     /**
223      * @return the path for sampling the graphs
224      */
225     public final List<Lane> getPath()
226     {
227         return this.path;
228     }
229 
230     /**
231      * <p>
232      * Copyright (c) 2013-2023 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
233      * <br>
234      * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
235      * </p>
236      * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
237      * @author <a href="https://tudelft.nl/staff/p.knoppers-1">Peter Knoppers</a>
238      * @author <a href="https://dittlab.tudelft.nl">Wouter Schakel</a>
239      */
240     private static class HeadwayGenerator implements Generator<Duration>
241     {
242         /** Demand level. */
243         private final Frequency demand;
244 
245         /** a random stream. */
246         private StreamInterface stream = new MersenneTwister(4L);
247 
248         /**
249          * @param demand Frequency; demand
250          */
251         HeadwayGenerator(final Frequency demand)
252         {
253             this.demand = demand;
254         }
255 
256         /** {@inheritDoc} */
257         @Override
258         public Duration draw() throws ProbabilityException, ParameterException
259         {
260             return new Duration(-Math.log(this.stream.nextDouble()) / this.demand.si, DurationUnit.SI);
261         }
262 
263     }
264 
265 }