1   package org.opentrafficsim.demo;
2   
3   import static org.opentrafficsim.core.gtu.GTUType.CAR;
4   import static org.opentrafficsim.core.gtu.GTUType.TRUCK;
5   
6   import java.awt.Dimension;
7   import java.io.InputStream;
8   import java.rmi.RemoteException;
9   import java.util.ArrayList;
10  import java.util.HashMap;
11  import java.util.LinkedHashSet;
12  import java.util.List;
13  import java.util.Map;
14  import java.util.Random;
15  import java.util.Set;
16  
17  import javax.naming.NamingException;
18  
19  import org.djunits.unit.AccelerationUnit;
20  import org.djunits.unit.DurationUnit;
21  import org.djunits.unit.FrequencyUnit;
22  import org.djunits.unit.LengthUnit;
23  import org.djunits.unit.SpeedUnit;
24  import org.djunits.value.vdouble.scalar.Acceleration;
25  import org.djunits.value.vdouble.scalar.Duration;
26  import org.djunits.value.vdouble.scalar.Frequency;
27  import org.djunits.value.vdouble.scalar.Length;
28  import org.djunits.value.vdouble.scalar.Speed;
29  import org.djunits.value.vdouble.scalar.Time;
30  import org.djutils.io.URLResource;
31  import org.opentrafficsim.base.parameters.ParameterException;
32  import org.opentrafficsim.base.parameters.ParameterSet;
33  import org.opentrafficsim.base.parameters.ParameterTypes;
34  import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer;
35  import org.opentrafficsim.core.distributions.ConstantGenerator;
36  import org.opentrafficsim.core.distributions.Distribution;
37  import org.opentrafficsim.core.distributions.Distribution.FrequencyAndObject;
38  import org.opentrafficsim.core.distributions.Generator;
39  import org.opentrafficsim.core.distributions.ProbabilityException;
40  import org.opentrafficsim.core.dsol.AbstractOTSModel;
41  import org.opentrafficsim.core.dsol.OTSAnimator;
42  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
43  import org.opentrafficsim.core.gtu.GTUDirectionality;
44  import org.opentrafficsim.core.gtu.GTUException;
45  import org.opentrafficsim.core.gtu.GTUType;
46  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterFactory;
47  import org.opentrafficsim.core.gtu.behavioralcharacteristics.ParameterFactoryByType;
48  import org.opentrafficsim.core.idgenerator.IdGenerator;
49  import org.opentrafficsim.core.network.LongitudinalDirectionality;
50  import org.opentrafficsim.core.network.NetworkException;
51  import org.opentrafficsim.core.network.OTSLink;
52  import org.opentrafficsim.core.network.OTSNetwork;
53  import org.opentrafficsim.core.network.OTSNode;
54  import org.opentrafficsim.core.network.route.ProbabilisticRouteGenerator;
55  import org.opentrafficsim.core.network.route.Route;
56  import org.opentrafficsim.core.network.route.RouteGenerator;
57  import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
58  import org.opentrafficsim.demo.ShortMerge.ShortMergeModel;
59  import org.opentrafficsim.draw.core.OTSDrawingException;
60  import org.opentrafficsim.road.gtu.colorer.LmrsSwitchableColorer;
61  import org.opentrafficsim.road.gtu.generator.GeneratorPositions;
62  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator;
63  import org.opentrafficsim.road.gtu.generator.LaneBasedGTUGenerator.RoomChecker;
64  import org.opentrafficsim.road.gtu.generator.TTCRoomChecker;
65  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUType;
66  import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedTemplateGTUTypeDistribution;
67  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
68  import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
69  import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
70  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
71  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
72  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationConflicts;
73  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationIncentive;
74  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationSpeedLimitTransition;
75  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationTrafficLights;
76  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
77  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveCourtesy;
78  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
79  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
80  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSocioSpeed;
81  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
82  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRS;
83  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
84  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
85  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
86  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
87  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
88  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
89  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
90  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
91  import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
92  import org.opentrafficsim.road.network.factory.xml.XmlNetworkLaneParser;
93  import org.opentrafficsim.road.network.lane.CrossSectionLink;
94  import org.opentrafficsim.road.network.lane.DirectedLanePosition;
95  import org.opentrafficsim.road.network.lane.Lane;
96  import org.opentrafficsim.road.network.lane.object.SpeedSign;
97  import org.opentrafficsim.swing.gui.AnimationToggles;
98  import org.opentrafficsim.swing.gui.OTSAnimationPanel;
99  import org.opentrafficsim.swing.gui.OTSSimulationApplication;
100 
101 import nl.tudelft.simulation.dsol.SimRuntimeException;
102 import nl.tudelft.simulation.jstats.distributions.DistNormal;
103 import nl.tudelft.simulation.jstats.distributions.DistUniform;
104 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
105 import nl.tudelft.simulation.jstats.streams.StreamInterface;
106 
107 
108 
109 
110 
111 
112 
113 
114 
115 
116 
117 public class ShortMerge extends OTSSimulationApplication<ShortMergeModel>
118 {
119     
120     private static final long serialVersionUID = 20170407L;
121 
122     
123     static final String NETWORK = "shortMerge";
124 
125     
126     static final double TRUCK_FRACTION = 0.15;
127 
128     
129     static final double LEFT_FRACTION = 0.3;
130 
131     
132     static final Frequency MAIN_DEMAND = new Frequency(1000, FrequencyUnit.PER_HOUR);
133 
134     
135     static final Frequency RAMP_DEMAND = new Frequency(200, FrequencyUnit.PER_HOUR);
136 
137     
138     static final Synchronization SYNCHRONIZATION = Synchronization.PASSIVE_MOVING;
139 
140     
141     static final Cooperation COOPERATION = Cooperation.PASSIVE_MOVING;
142 
143     
144     static final boolean ADDITIONAL_INCENTIVES = true;
145 
146     
147     public static final Time SIMTIME = Time.createSI(3600);
148 
149     
150 
151 
152 
153 
154 
155 
156     public ShortMerge(final String title, final OTSAnimationPanel panel, final ShortMergeModel model) throws OTSDrawingException
157     {
158         super(model, panel);
159     }
160 
161     
162     @Override
163     protected void setAnimationToggles()
164     {
165         AnimationToggles.setTextAnimationTogglesFull(getAnimationPanel());
166         getAnimationPanel().getAnimationPanel().toggleClass(OTSLink.class);
167         getAnimationPanel().getAnimationPanel().toggleClass(OTSNode.class);
168         getAnimationPanel().getAnimationPanel().showClass(SpeedSign.class);
169     }
170 
171     
172 
173 
174 
175     public static void main(final String[] args)
176     {
177         demo(true);
178     }
179 
180     
181 
182 
183 
184     public static void demo(final boolean exitOnClose)
185     {
186         try
187         {
188             OTSAnimator simulator = new OTSAnimator();
189             final ShortMergeModel otsModel = new ShortMergeModel(simulator);
190             simulator.initialize(Time.ZERO, Duration.ZERO, Duration.createSI(3600.0), otsModel);
191             OTSAnimationPanel animationPanel = new OTSAnimationPanel(otsModel.getNetwork().getExtent(), new Dimension(800, 600),
192                     simulator, otsModel, new LmrsSwitchableColorer(), otsModel.getNetwork());
193             ShortMerge app = new ShortMerge("ShortMerge", animationPanel, otsModel);
194             app.setExitOnClose(exitOnClose);
195         }
196         catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException exception)
197         {
198             exception.printStackTrace();
199         }
200     }
201 
202     
203 
204 
205 
206 
207 
208 
209 
210 
211 
212 
213     static class ShortMergeModel extends AbstractOTSModel
214     {
215         
216         private static final long serialVersionUID = 20170407L;
217 
218         
219         private OTSNetwork network;
220 
221         
222 
223 
224         ShortMergeModel(final OTSSimulatorInterface simulator)
225         {
226             super(simulator);
227         }
228 
229         
230 
231 
232         public void setNetwork(final OTSNetwork network)
233         {
234             this.network = network;
235         }
236 
237         
238         @Override
239         public void constructModel() throws SimRuntimeException
240         {
241             try
242             {
243                 InputStream stream = URLResource.getResourceAsStream("/lmrs/" + NETWORK + ".xml");
244                 XmlNetworkLaneParser nlp = new XmlNetworkLaneParser(this.simulator);
245                 this.network = new OTSNetwork("ShortMerge");
246                 nlp.build(stream, this.network, false);
247 
248                 addGenerator();
249 
250             }
251             catch (Exception exception)
252             {
253                 exception.printStackTrace();
254             }
255         }
256 
257         
258         @Override
259         public OTSNetwork getNetwork()
260         {
261             return this.network;
262         }
263 
264         
265 
266 
267 
268 
269 
270 
271 
272 
273         private void addGenerator() throws ParameterException, GTUException, NetworkException, ProbabilityException,
274                 SimRuntimeException, RemoteException
275         {
276 
277             Random seedGenerator = new Random(1L);
278             Map<String, StreamInterface> streams = new HashMap<>();
279             StreamInterface stream = new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1);
280             streams.put("headwayGeneration", stream);
281             streams.put("gtuClass", new MersenneTwister(Math.abs(seedGenerator.nextLong()) + 1));
282             this.getSimulator().getReplication().setStreams(streams);
283 
284             TTCRoomChecker roomChecker = new TTCRoomChecker(new Duration(10.0, DurationUnit.SI));
285             IdGenerator idGenerator = new IdGenerator("");
286 
287             CarFollowingModelFactory<IDMPlus> idmPlusFactory = new IDMPlusFactory(streams.get("gtuClass"));
288             ParameterSet params = new ParameterSet();
289             params.setDefaultParameter(AbstractIDM.DELTA);
290 
291             Set<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
292             Set<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
293             Set<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
294             mandatoryIncentives.add(new IncentiveRoute());
295             if (ADDITIONAL_INCENTIVES)
296             {
297                 
298             }
299             voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
300             voluntaryIncentives.add(new IncentiveKeep());
301             if (ADDITIONAL_INCENTIVES)
302             {
303                 voluntaryIncentives.add(new IncentiveCourtesy());
304                 voluntaryIncentives.add(new IncentiveSocioSpeed());
305             }
306             accelerationIncentives.add(new AccelerationSpeedLimitTransition());
307             accelerationIncentives.add(new AccelerationTrafficLights());
308             accelerationIncentives.add(new AccelerationConflicts());
309             LaneBasedTacticalPlannerFactory<LMRS> tacticalFactory = new LMRSFactory(idmPlusFactory,
310                     new DefaultLMRSPerceptionFactory(), SYNCHRONIZATION, COOPERATION, GapAcceptance.INFORMED, Tailgating.NONE,
311                     mandatoryIncentives, voluntaryIncentives, accelerationIncentives);
312 
313             GTUType car = new GTUType("car", CAR);
314             GTUType truck = new GTUType("truck", TRUCK);
315             Route routeAE = this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("E"));
316             Route routeAG = !NETWORK.equals("shortWeave") ? null
317                     : this.network.getShortestRouteBetween(car, this.network.getNode("A"), this.network.getNode("G"));
318             Route routeFE = this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("E"));
319             Route routeFG = !NETWORK.equals("shortWeave") ? null
320                     : this.network.getShortestRouteBetween(car, this.network.getNode("F"), this.network.getNode("G"));
321 
322             double leftFraction = NETWORK.equals("shortWeave") ? LEFT_FRACTION : 0.0;
323             List<FrequencyAndObject<Route>> routesA = new ArrayList<>();
324             routesA.add(new FrequencyAndObject<>(1.0 - leftFraction, routeAE));
325             routesA.add(new FrequencyAndObject<>(leftFraction, routeAG));
326             List<FrequencyAndObject<Route>> routesF = new ArrayList<>();
327             routesF.add(new FrequencyAndObject<>(1.0 - leftFraction, routeFE));
328             routesF.add(new FrequencyAndObject<>(leftFraction, routeFG));
329             RouteGenerator routeGeneratorA = new ProbabilisticRouteGenerator(routesA, stream);
330             RouteGenerator routeGeneratorF = new ProbabilisticRouteGenerator(routesF, stream);
331 
332             Speed speedA = new Speed(120.0, SpeedUnit.KM_PER_HOUR);
333             Speed speedF = new Speed(20.0, SpeedUnit.KM_PER_HOUR);
334 
335             CrossSectionLink linkA = (CrossSectionLink) this.network.getLink("AB");
336             CrossSectionLink linkF = (CrossSectionLink) this.network.getLink("FF2");
337 
338             ParameterFactoryByType bcFactory = new ParameterFactoryByType();
339             bcFactory.addParameter(car, ParameterTypes.FSPEED, new DistNormal(stream, 123.7 / 120, 12.0 / 120));
340             bcFactory.addParameter(car, LmrsParameters.SOCIO, new DistNormal(stream, 0.5, 0.1));
341             bcFactory.addParameter(truck, ParameterTypes.A, new Acceleration(0.8, AccelerationUnit.SI));
342             bcFactory.addParameter(truck, LmrsParameters.SOCIO, new DistNormal(stream, 0.5, 0.1));
343             bcFactory.addParameter(Tailgating.RHO, Tailgating.RHO.getDefaultValue());
344 
345             Generator<Duration> headwaysA1 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
346             Generator<Duration> headwaysA2 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
347             Generator<Duration> headwaysA3 = new HeadwayGenerator(getSimulator(), MAIN_DEMAND);
348             Generator<Duration> headwaysF = new HeadwayGenerator(getSimulator(), RAMP_DEMAND);
349 
350             
351             ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedCar =
352                     new ContinuousDistDoubleScalar.Rel<>(new DistUniform(stream, 160, 200), SpeedUnit.KM_PER_HOUR);
353             ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> speedTruck =
354                     new ContinuousDistDoubleScalar.Rel<>(new DistUniform(stream, 80, 95), SpeedUnit.KM_PER_HOUR);
355             
356             LaneBasedStrategicalRoutePlannerFactory strategicalFactory =
357                     new LaneBasedStrategicalRoutePlannerFactory(tacticalFactory, bcFactory);
358             
359             LaneBasedTemplateGTUType carA =
360                     new LaneBasedTemplateGTUType(new GTUType("car", CAR), new ConstantGenerator<>(Length.createSI(4.0)),
361                             new ConstantGenerator<>(Length.createSI(2.0)), speedCar, strategicalFactory, routeGeneratorA);
362             LaneBasedTemplateGTUType carF =
363                     new LaneBasedTemplateGTUType(new GTUType("car", CAR), new ConstantGenerator<>(Length.createSI(4.0)),
364                             new ConstantGenerator<>(Length.createSI(2.0)), speedCar, strategicalFactory, routeGeneratorF);
365             LaneBasedTemplateGTUType truckA =
366                     new LaneBasedTemplateGTUType(new GTUType("truck", TRUCK), new ConstantGenerator<>(Length.createSI(15.0)),
367                             new ConstantGenerator<>(Length.createSI(2.5)), speedTruck, strategicalFactory, routeGeneratorA);
368             LaneBasedTemplateGTUType truckF =
369                     new LaneBasedTemplateGTUType(new GTUType("truck", TRUCK), new ConstantGenerator<>(Length.createSI(15.0)),
370                             new ConstantGenerator<>(Length.createSI(2.5)), speedTruck, strategicalFactory, routeGeneratorF);
371             
372             Distribution<LaneBasedTemplateGTUType> gtuTypeAllCarA = new Distribution<>(streams.get("gtuClass"));
373             gtuTypeAllCarA.add(new FrequencyAndObject<>(1.0, carA));
374 
375             Distribution<LaneBasedTemplateGTUType> gtuType1LaneF = new Distribution<>(streams.get("gtuClass"));
376             gtuType1LaneF.add(new FrequencyAndObject<>(1.0 - 2 * TRUCK_FRACTION, carF));
377             gtuType1LaneF.add(new FrequencyAndObject<>(2 * TRUCK_FRACTION, truckF));
378 
379             Distribution<LaneBasedTemplateGTUType> gtuType2ndLaneA = new Distribution<>(streams.get("gtuClass"));
380             gtuType2ndLaneA.add(new FrequencyAndObject<>(1.0 - 2 * TRUCK_FRACTION, carA));
381             gtuType2ndLaneA.add(new FrequencyAndObject<>(2 * TRUCK_FRACTION, truckA));
382 
383             Distribution<LaneBasedTemplateGTUType> gtuType3rdLaneA = new Distribution<>(streams.get("gtuClass"));
384             gtuType3rdLaneA.add(new FrequencyAndObject<>(1.0 - 3 * TRUCK_FRACTION, carA));
385             gtuType3rdLaneA.add(new FrequencyAndObject<>(3 * TRUCK_FRACTION, truckA));
386 
387             GTUColorer colorer = new LmrsSwitchableColorer();
388             makeGenerator(getLane(linkA, "FORWARD1"), speedA, "gen1", idGenerator, gtuTypeAllCarA, headwaysA1, colorer,
389                     roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
390             if (NETWORK.equals("shortWeave"))
391             {
392                 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", idGenerator, gtuTypeAllCarA, headwaysA2, colorer,
393                         roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
394                 makeGenerator(getLane(linkA, "FORWARD3"), speedA, "gen3", idGenerator, gtuType3rdLaneA, headwaysA3, colorer,
395                         roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
396             }
397             else
398             {
399                 makeGenerator(getLane(linkA, "FORWARD2"), speedA, "gen2", idGenerator, gtuType2ndLaneA, headwaysA2, colorer,
400                         roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
401             }
402             makeGenerator(getLane(linkF, "FORWARD1"), speedF, "gen4", idGenerator, gtuType1LaneF, headwaysF, colorer,
403                     roomChecker, bcFactory, tacticalFactory, SIMTIME, streams.get("gtuClass"));
404 
405             new SpeedSign("sign1", getLane(linkA, "FORWARD1"), LongitudinalDirectionality.DIR_PLUS, Length.createSI(10),
406                     this.getSimulator(), new Speed(130.0, SpeedUnit.KM_PER_HOUR));
407 
408         }
409 
410         
411 
412 
413 
414 
415 
416         private Lane getLane(final CrossSectionLink link, final String id)
417         {
418             return (Lane) link.getCrossSectionElement(id);
419         }
420 
421         
422 
423 
424 
425 
426 
427 
428 
429 
430 
431 
432 
433 
434 
435 
436 
437 
438 
439         private void makeGenerator(final Lane lane, final Speed generationSpeed, final String id, final IdGenerator idGenerator,
440                 final Distribution<LaneBasedTemplateGTUType> distribution, final Generator<Duration> headwayGenerator,
441                 final GTUColorer gtuColorer, final RoomChecker roomChecker, final ParameterFactory bcFactory,
442                 final LaneBasedTacticalPlannerFactory<?> tacticalFactory, final Time simulationTime,
443                 final StreamInterface stream) throws SimRuntimeException, ProbabilityException, GTUException, ParameterException
444         {
445 
446             Set<DirectedLanePosition> initialLongitudinalPositions = new LinkedHashSet<>();
447             
448             initialLongitudinalPositions
449                     .add(new DirectedLanePosition(lane, new Length(5.0, LengthUnit.SI), GTUDirectionality.DIR_PLUS));
450             LaneBasedTemplateGTUTypeDistribution characteristicsGenerator =
451                     new LaneBasedTemplateGTUTypeDistribution(distribution);
452             new LaneBasedGTUGenerator(id, headwayGenerator, characteristicsGenerator,
453                     GeneratorPositions.create(initialLongitudinalPositions, stream), this.network, getSimulator(), roomChecker,
454                     idGenerator);
455         }
456 
457     }
458 
459     
460 
461 
462 
463 
464 
465 
466 
467 
468 
469 
470     private static class HeadwayGenerator implements Generator<Duration>
471     {
472         
473         private final OTSSimulatorInterface simulator;
474 
475         
476         private final Frequency demand;
477 
478         
479 
480 
481 
482         HeadwayGenerator(final OTSSimulatorInterface simulator, final Frequency demand)
483         {
484             this.simulator = simulator;
485             this.demand = demand;
486         }
487 
488         
489         @Override
490         public Duration draw() throws ProbabilityException, ParameterException
491         {
492             return new Duration(
493                     -Math.log(this.simulator.getReplication().getStream("headwayGeneration").nextDouble()) / this.demand.si,
494                     DurationUnit.SI);
495         }
496 
497     }
498 
499 }