View Javadoc
1   package org.opentrafficsim.demo.carFollowing;
2   
3   import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.CAR;
4   import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.TRUCK;
5   
6   import java.io.InputStream;
7   import java.rmi.RemoteException;
8   import java.util.ArrayList;
9   import java.util.HashMap;
10  import java.util.HashSet;
11  import java.util.List;
12  import java.util.Map;
13  import java.util.Random;
14  import java.util.Set;
15  
16  import org.djunits.unit.AccelerationUnit;
17  import org.djunits.unit.FrequencyUnit;
18  import org.djunits.unit.LengthUnit;
19  import org.djunits.unit.SpeedUnit;
20  import org.djunits.unit.TimeUnit;
21  import org.djunits.value.vdouble.scalar.Acceleration;
22  import org.djunits.value.vdouble.scalar.Duration;
23  import org.djunits.value.vdouble.scalar.Frequency;
24  import org.djunits.value.vdouble.scalar.Length;
25  import org.djunits.value.vdouble.scalar.Speed;
26  import org.djunits.value.vdouble.scalar.Time;
27  import org.opentrafficsim.base.modelproperties.Property;
28  import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
29  import org.opentrafficsim.core.distributions.Generator;
30  import org.opentrafficsim.core.distributions.ProbabilityException;
31  import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface;
32  import org.opentrafficsim.core.dsol.OTSModelInterface;
33  import org.opentrafficsim.core.dsol.OTSSimTimeDouble;
34  import org.opentrafficsim.core.gtu.GTUDirectionality;
35  import org.opentrafficsim.core.gtu.GTUException;
36  import org.opentrafficsim.core.gtu.GTUType;
37  import org.opentrafficsim.core.gtu.animation.GTUColorer;
38  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics;
39  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactory;
40  import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristicsFactoryByType;
41  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterException;
42  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterTypes;
43  import org.opentrafficsim.core.idgenerator.IdGenerator;
44  import org.opentrafficsim.core.network.NetworkException;
45  import org.opentrafficsim.core.network.OTSLink;
46  import org.opentrafficsim.core.network.OTSNetwork;
47  import org.opentrafficsim.core.network.OTSNode;
48  import org.opentrafficsim.core.network.route.ProbabilisticRouteGenerator;
49  import org.opentrafficsim.core.network.route.Route;
50  import org.opentrafficsim.core.network.route.RouteGenerator;
51  import org.opentrafficsim.road.animation.AnimationToggles;
52  import org.opentrafficsim.road.gtu.generator.CharacteristicsGenerator;
53  import org.opentrafficsim.road.gtu.generator.GTUTypeGenerator;
54  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
55  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
56  import org.opentrafficsim.road.gtu.generator.SpeedGenerator;
57  import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
58  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
59  import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
60  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
61  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
62  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
63  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
64  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
65  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
66  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
67  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
68  import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
69  import org.opentrafficsim.road.network.lane.CrossSectionLink;
70  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
71  import org.opentrafficsim.road.network.lane.Lane;
72  import org.opentrafficsim.simulationengine.AbstractWrappableAnimation;
73  import org.opentrafficsim.simulationengine.OTSSimulationException;
74  
75  import nl.tudelft.simulation.dsol.SimRuntimeException;
76  import nl.tudelft.simulation.dsol.simulators.SimulatorInterface;
77  import nl.tudelft.simulation.jstats.streams.MersenneTwister;
78  import nl.tudelft.simulation.jstats.streams.StreamInterface;
79  import nl.tudelft.simulation.language.io.URLResource;
80  
81  /**
82   * <p>
83   * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
84   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
85   * <p>
86   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 7 apr. 2017 <br>
87   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
88   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
89   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
90   */
91  public class ShortMerge extends AbstractWrappableAnimation
92  {
93  
94      /** Simulation time. */
95      public static final Time SIMTIME = Time.createSI(3600);
96  
97      /** */
98      private static final long serialVersionUID = 20170407L;
99  
100     /** The simulator. */
101     private OTSDEVSSimulatorInterface sim;
102 
103     /** {@inheritDoc} */
104     @Override
105     public String shortName()
106     {
107         return "ShortMerge";
108     }
109 
110     /** {@inheritDoc} */
111     @Override
112     public String description()
113     {
114         return "Short merge to test lane change models.";
115     }
116 
117     /** {@inheritDoc} */
118     @Override
119     protected final void addAnimationToggles()
120     {
121         AnimationToggles.setTextAnimationTogglesFull(this);
122         this.toggleAnimationClass(OTSLink.class);
123         this.toggleAnimationClass(OTSNode.class);
124     }
125 
126     /** {@inheritDoc} */
127     @Override
128     protected OTSModelInterface makeModel(final GTUColorer colorer) throws OTSSimulationException
129     {
130         return new ShortMergeModel(colorer);
131     }
132 
133     /**
134      * @return simulator.
135      */
136     public OTSDEVSSimulatorInterface getSimulator()
137     {
138         return this.sim;
139     }
140 
141     /**
142      * @param simulator set simulator.
143      */
144     public void setSimulator(final OTSDEVSSimulatorInterface simulator)
145     {
146         this.sim = simulator;
147     }
148 
149     /**
150      * Main method.
151      * @param args args for main program
152      */
153     public static void main(final String[] args)
154     {
155 
156         ShortMerge shortMerge = new ShortMerge();
157         try
158         {
159             shortMerge.buildAnimator(Time.ZERO, Duration.ZERO, Duration.createSI(SIMTIME.si), new ArrayList<Property<?>>(),
160                     null, true);
161         }
162         catch (Exception exception)
163         {
164             exception.printStackTrace();
165         }
166 
167     }
168 
169     /**
170      * <p>
171      * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
172      * <br>
173      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
174      * <p>
175      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 7 apr. 2017 <br>
176      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
177      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
178      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
179      */
180     class ShortMergeModel implements OTSModelInterface
181     {
182 
183         /**
184          * @param network set network.
185          */
186         public void setNetwork(final OTSNetwork network)
187         {
188             this.network = network;
189         }
190 
191         /** */
192         private static final long serialVersionUID = 20170407L;
193 
194         /** The network. */
195         private OTSNetwork network;
196 
197         /** Colorer. */
198         private final GTUColorer colorer;
199 
200         /**
201          * @param colorer colorer
202          */
203         ShortMergeModel(final GTUColorer colorer)
204         {
205             this.colorer = colorer;
206         }
207 
208         /** {@inheritDoc} */
209         @Override
210         public void constructModel(final SimulatorInterface<Time, Duration, OTSSimTimeDouble> simulator)
211                 throws SimRuntimeException, RemoteException
212         {
213             ShortMerge.this.setSimulator((OTSDEVSSimulatorInterface) simulator);
214 
215             try
216             {
217                 InputStream stream = URLResource.getResourceAsStream("/lmrs/shortMerge.xml");
218                 XmlNetworkLaneParser nlp = new XmlNetworkLaneParser((OTSDEVSSimulatorInterface) simulator);
219                 this.network = new OTSNetwork("ShortMerge");
220                 nlp.build(stream, this.network);
221 
222                 addGenerator();
223 
224             }
225             catch (Exception exception)
226             {
227                 exception.printStackTrace();
228             }
229         }
230 
231         /** {@inheritDoc} */
232         @Override
233         public SimulatorInterface<Time, Duration, OTSSimTimeDouble> getSimulator() throws RemoteException
234         {
235             return ShortMerge.this.getSimulator();
236         }
237 
238         /** {@inheritDoc} */
239         @Override
240         public OTSNetwork getNetwork()
241         {
242             return this.network;
243         }
244 
245         /**
246          * Create generators.
247          * @throws ParameterException on parameter exception
248          * @throws GTUException on GTU exception
249          * @throws NetworkException if not does not exist
250          * @throws ProbabilityException negative probability
251          * @throws SimRuntimeException in case of sim run time exception
252          * @throws RemoteException if no simulator
253          */
254         private void addGenerator() throws ParameterException, GTUException, NetworkException, ProbabilityException,
255                 SimRuntimeException, RemoteException
256         {
257 
258             Random seedGenerator = new Random(1L);
259             Map<String, StreamInterface> streams = new HashMap<>();
260             StreamInterface stream = new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1);
261             streams.put("headwayGeneration", stream);
262             streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
263             this.getSimulator().getReplication().setStreams(streams);
264 
265             TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, TimeUnit.SI));
266             IdGenerator idGenerator = new IdGenerator("");
267 
268             CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory();
269             BehavioralCharacteristics bc = new BehavioralCharacteristics();
270             bc.setDefaultParameter(AbstractIDM.DELTA);
271 
272             LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory =
273                     new LMRSFactory(idmPlusFactory, bc, new DefaultLMRSPerceptionFactory());
274 
275             GTUType car = new GTUType("car", CAR);
276             GTUType truck = new GTUType("truck", TRUCK);
277             Route routeAE = this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("E"));
278             Route routeAG = this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("G"));
279             Route routeFE = this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("E"));
280             Route routeFG = this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("G"));
281 
282             List<FrequencyAndObject<Route>> routesA = new ArrayList<>();
283             routesA.add(new FrequencyAndObject<>(0.2, routeAE));
284             routesA.add(new FrequencyAndObject<>(0.8, routeAG));
285             List<FrequencyAndObject<Route>> routesF = new ArrayList<>();
286             routesF.add(new FrequencyAndObject<>(0.2, routeFE));
287             routesF.add(new FrequencyAndObject<>(0.8, routeFG));
288             RouteGenerator routeGeneratorA = new ProbabilisticRouteGenerator(routesA, stream);
289             RouteGenerator routeGeneratorF = new ProbabilisticRouteGenerator(routesF, stream);
290 
291             Speed speedA = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
292             Speed speedF = new Speed(20.0, SpeedUnit.KM_PER_HOUR);
293 
294             CrossSectionLink linkA = (CrossSectionLink) this.network.getLink("AB");
295             CrossSectionLink linkF = (CrossSectionLink) this.network.getLink("FB");
296 
297             BehavioralCharacteristicsFactoryByType bcFactory = new BehavioralCharacteristicsFactoryByType();
298             bcFactory.addGaussianParameter(car, ParameterTypes.FSPEED, 123.7 / 120, 12.0 / 120, stream);
299             bcFactory.addGaussianParameter(car, LmrsParameters.HIERARCHY, 0.5, 0.1, stream);
300             bcFactory.addParameter(truck, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
301             bcFactory.addGaussianParameter(truck, LmrsParameters.HIERARCHY, 0.5, 0.1, stream);
302 
303             Generator<Duration> headwaysA1 = new HeadwayGenerator(new Frequency(400, FrequencyUnit.PER_HOUR));
304             Generator<Duration> headwaysA2 = new HeadwayGenerator(new Frequency(400, FrequencyUnit.PER_HOUR));
305             Generator<Duration> headwaysA3 = new HeadwayGenerator(new Frequency(400, FrequencyUnit.PER_HOUR));
306             Generator<Duration> headwaysF = new HeadwayGenerator(new Frequency(600, FrequencyUnit.PER_HOUR));
307 
308             SpeedGenerator speedCar = new SpeedGenerator(new Speed(160.0, SpeedUnit.KM_PER_HOUR),
309                     new Speed(200.0, SpeedUnit.KM_PER_HOUR), stream);
310             SpeedGenerator speedTruck =
311                     new SpeedGenerator(new Speed(80.0, SpeedUnit.KM_PER_HOUR), new Speed(95.0, SpeedUnit.KM_PER_HOUR), stream);
312             GTUTypeGenerator gtuTypeAllCar = new GTUTypeGenerator(ShortMerge.this.getSimulator());
313             GTUTypeGenerator gtuType1Lane = new GTUTypeGenerator(ShortMerge.this.getSimulator());
314             GTUTypeGenerator gtuType3rdLane = new GTUTypeGenerator(ShortMerge.this.getSimulator());
315             gtuTypeAllCar.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
316                     speedCar, 1.0);
317             gtuType1Lane.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
318                     speedCar, 0.9);
319             gtuType1Lane.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI), new GTUType("truck", TRUCK),
320                     speedTruck, 0.1);
321             gtuType3rdLane.addType(new Length(4.0, LengthUnit.SI), new Length(2.0, LengthUnit.SI), new GTUType("car", CAR),
322                     speedCar, 0.7);
323             gtuType3rdLane.addType(new Length(15.0, LengthUnit.SI), new Length(2.5, LengthUnit.SI), new GTUType("truck", TRUCK),
324                     speedTruck, 0.3);
325 
326             makeGenerator(getLane(linkA, "FORWARD1"), speedA, "gen1", routeGeneratorA, idGenerator, gtuTypeAllCar, headwaysA1,
327                     this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
328             makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", routeGeneratorA, idGenerator, gtuTypeAllCar, headwaysA2,
329                     this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
330             makeGenerator(getLane(linkA, "FORWARD3"), speedA, "gen3", routeGeneratorA, idGenerator, gtuType3rdLane, headwaysA3,
331                     this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
332             makeGenerator(getLane(linkF, "FORWARD1"), speedF, "gen4", routeGeneratorF, idGenerator, gtuType1Lane, headwaysF,
333                     this.colorer, roomChecker, bcFactory, tacticalFactory, SIMTIME);
334 
335         }
336 
337         /**
338          * Get lane from link by id.
339          * @param link link
340          * @param id id
341          * @return lane
342          */
343         private Lane getLane(final CrossSectionLink link, final String id)
344         {
345             for (Lane lane : link.getLanes())
346             {
347                 if (lane.getId().equals(id))
348                 {
349                     return lane;
350                 }
351             }
352             throw new RuntimeException("Could not find lane " + id + " on link " + link.getId());
353         }
354 
355         /**
356          * @param lane the reference lane for this generator
357          * @param generationSpeed the speed of the GTU
358          * @param id the id of the generator itself
359          * @param routeGenerator the generator for the route
360          * @param idGenerator the generator for the ID
361          * @param gtuTypeGenerator the type generator for the GTU
362          * @param headwayGenerator the headway generator for the GTU
363          * @param gtuColorer the GTU colorer for animation
364          * @param roomChecker the checker to see if there is room for the GTU
365          * @param bcFactory the factory to generate behavioral characteristics for the GTU
366          * @param tacticalFactory the generator for the tactical planner
367          * @param simulationTime simulation time
368          * @throws SimRuntimeException in case of scheduling problems
369          * @throws ProbabilityException in case of an illegal probability distribution
370          * @throws GTUException in case the GTU is inconsistent
371          * @throws ParameterException in case a parameter for the perception is missing
372          */
373         private void makeGenerator(final Lane lane, final Speed generationSpeed, final String id,
374                 final RouteGenerator routeGenerator, final IdGenerator idGenerator, final GTUTypeGenerator gtuTypeGenerator,
375                 final Generator<Duration> headwayGenerator, final GTUColorer gtuColorer, final RoomChecker roomChecker,
376                 final BehavioralCharacteristicsFactory bcFactory, final LaneBasedTacticalPlannerFactory<?> tacticalFactory,
377                 final Time simulationTime) throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
378         {
379             Set<DirectedLanePosition> initialLongitudinalPositions = new HashSet<>();
380             // TODO DIR_MINUS
381             initialLongitudinalPositions
382                     .add(new DirectedLanePosition(lane, new Length(10.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
383 
384             LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
385                     new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
386 
387             CharacteristicsGenerator characteristicsGenerator = new CharacteristicsGenerator(strategicalFactory, routeGenerator,
388                     idGenerator, ShortMerge.this.getSimulator(), this.network, gtuTypeGenerator, generationSpeed,
389                     initialLongitudinalPositions);
390 
391             new LaneBasedGTUGenerator(id, headwayGenerator, Long.MAX_VALUE, Time.ZERO, simulationTime, gtuColorer,
392                     characteristicsGenerator, initialLongitudinalPositions, this.network, roomChecker);
393         }
394 
395     }
396 
397     /**
398      * <p>
399      * Copyright (c) 2013-2016 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
400      * <br>
401      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
402      * <p>
403      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 29 jan. 2017 <br>
404      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
405      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
406      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
407      */
408     private class HeadwayGenerator implements Generator<Duration>
409     {
410 
411         /** Demand level. */
412         private final Frequency demand;
413 
414         /**
415          * @param demand demand
416          */
417         HeadwayGenerator(final Frequency demand)
418         {
419             this.demand = demand;
420         }
421 
422         /** {@inheritDoc} */
423         @Override
424         public Duration draw() throws ProbabilityException, ParameterException
425         {
426             return new Duration(
427                     -Math.log(ShortMerge.this.getSimulator().getReplication().getStream("headwayGeneration").nextDouble())
428                             / this.demand.si,
429                     TimeUnit.SI);
430         }
431 
432     }
433 
434 }