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