View Javadoc
1   package strategies;
2   
3   import java.awt.Color;
4   import java.awt.Dimension;
5   import java.awt.Toolkit;
6   import java.io.BufferedWriter;
7   import java.io.IOException;
8   import java.io.Serializable;
9   import java.rmi.RemoteException;
10  import java.util.ArrayList;
11  import java.util.LinkedHashMap;
12  import java.util.LinkedHashSet;
13  import java.util.List;
14  import java.util.Map;
15  import java.util.Set;
16  
17  import javax.naming.NamingException;
18  
19  import org.djunits.unit.FrequencyUnit;
20  import org.djunits.unit.SpeedUnit;
21  import org.djunits.unit.TimeUnit;
22  import org.djunits.value.ValueRuntimeException;
23  import org.djunits.value.storage.StorageType;
24  import org.djunits.value.vdouble.scalar.Acceleration;
25  import org.djunits.value.vdouble.scalar.Direction;
26  import org.djunits.value.vdouble.scalar.Duration;
27  import org.djunits.value.vdouble.scalar.Frequency;
28  import org.djunits.value.vdouble.scalar.Length;
29  import org.djunits.value.vdouble.scalar.Speed;
30  import org.djunits.value.vdouble.scalar.Time;
31  import org.djunits.value.vdouble.vector.FrequencyVector;
32  import org.djunits.value.vdouble.vector.TimeVector;
33  import org.djunits.value.vdouble.vector.base.DoubleVector;
34  import org.djunits.value.vfloat.scalar.FloatDuration;
35  import org.djunits.value.vfloat.scalar.FloatLength;
36  import org.djunits.value.vfloat.scalar.FloatSpeed;
37  import org.djutils.event.EventInterface;
38  import org.djutils.event.EventListenerInterface;
39  import org.djutils.exceptions.Throw;
40  import org.djutils.exceptions.Try;
41  import org.opentrafficsim.base.CompressedFileWriter;
42  import org.opentrafficsim.base.parameters.ParameterException;
43  import org.opentrafficsim.base.parameters.ParameterSet;
44  import org.opentrafficsim.base.parameters.ParameterTypes;
45  import org.opentrafficsim.base.parameters.Parameters;
46  import org.opentrafficsim.core.animation.gtu.colorer.AccelerationGTUColorer;
47  import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer;
48  import org.opentrafficsim.core.animation.gtu.colorer.IDGTUColorer;
49  import org.opentrafficsim.core.animation.gtu.colorer.SpeedGTUColorer;
50  import org.opentrafficsim.core.animation.gtu.colorer.SwitchableGTUColorer;
51  import org.opentrafficsim.core.compatibility.Compatible;
52  import org.opentrafficsim.core.dsol.AbstractOTSModel;
53  import org.opentrafficsim.core.dsol.AbstractOTSSimulationApplication;
54  import org.opentrafficsim.core.dsol.OTSAnimator;
55  import org.opentrafficsim.core.dsol.OTSModelInterface;
56  import org.opentrafficsim.core.dsol.OTSSimulator;
57  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
58  import org.opentrafficsim.core.geometry.OTSGeometryException;
59  import org.opentrafficsim.core.geometry.OTSLine3D;
60  import org.opentrafficsim.core.geometry.OTSPoint3D;
61  import org.opentrafficsim.core.gtu.GTU;
62  import org.opentrafficsim.core.gtu.GTUCharacteristics;
63  import org.opentrafficsim.core.gtu.GTUException;
64  import org.opentrafficsim.core.gtu.GTUType;
65  import org.opentrafficsim.core.gtu.perception.DirectEgoPerception;
66  import org.opentrafficsim.core.network.LateralDirectionality;
67  import org.opentrafficsim.core.network.LinkType;
68  import org.opentrafficsim.core.network.Network;
69  import org.opentrafficsim.core.network.NetworkException;
70  import org.opentrafficsim.core.network.Node;
71  import org.opentrafficsim.core.network.OTSLink;
72  import org.opentrafficsim.core.network.OTSNode;
73  import org.opentrafficsim.core.parameters.ParameterFactoryByType;
74  import org.opentrafficsim.core.units.distributions.ContinuousDistDoubleScalar;
75  import org.opentrafficsim.core.units.distributions.ContinuousDistSpeed;
76  import org.opentrafficsim.draw.core.OTSDrawingException;
77  import org.opentrafficsim.draw.gtu.GtuGeneratorQueueAnimation;
78  import org.opentrafficsim.draw.network.LinkAnimation;
79  import org.opentrafficsim.draw.network.NodeAnimation;
80  import org.opentrafficsim.draw.road.LaneAnimation;
81  import org.opentrafficsim.draw.road.StripeAnimation;
82  import org.opentrafficsim.draw.road.StripeAnimation.TYPE;
83  import org.opentrafficsim.kpi.sampling.KpiGtuDirectionality;
84  import org.opentrafficsim.kpi.sampling.KpiLaneDirection;
85  import org.opentrafficsim.kpi.sampling.Sampler;
86  import org.opentrafficsim.kpi.sampling.SpaceTimeRegion;
87  import org.opentrafficsim.kpi.sampling.data.ExtendedDataTypeDuration;
88  import org.opentrafficsim.kpi.sampling.data.ExtendedDataTypeLength;
89  import org.opentrafficsim.kpi.sampling.data.ExtendedDataTypeNumber;
90  import org.opentrafficsim.kpi.sampling.data.ExtendedDataTypeSpeed;
91  import org.opentrafficsim.road.gtu.colorer.DesiredHeadwayColorer;
92  import org.opentrafficsim.road.gtu.colorer.DesiredSpeedColorer;
93  import org.opentrafficsim.road.gtu.colorer.FixedColor;
94  import org.opentrafficsim.road.gtu.colorer.GTUTypeColorer;
95  import org.opentrafficsim.road.gtu.colorer.IncentiveColorer;
96  import org.opentrafficsim.road.gtu.colorer.SocialPressureColorer;
97  import org.opentrafficsim.road.gtu.colorer.SynchronizationColorer;
98  import org.opentrafficsim.road.gtu.colorer.TotalDesireColorer;
99  import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBias;
100 import org.opentrafficsim.road.gtu.generator.GeneratorPositions.LaneBiases;
101 import org.opentrafficsim.road.gtu.generator.GtuGeneratorQueue;
102 import org.opentrafficsim.road.gtu.generator.MarkovCorrelation;
103 import org.opentrafficsim.road.gtu.generator.characteristics.LaneBasedGTUCharacteristics;
104 import org.opentrafficsim.road.gtu.generator.headway.ArrivalsHeadwayGenerator.HeadwayDistribution;
105 import org.opentrafficsim.road.gtu.generator.od.GTUCharacteristicsGeneratorOD;
106 import org.opentrafficsim.road.gtu.generator.od.ODApplier;
107 import org.opentrafficsim.road.gtu.generator.od.ODApplier.GeneratorObjects;
108 import org.opentrafficsim.road.gtu.generator.od.ODOptions;
109 import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
110 import org.opentrafficsim.road.gtu.lane.VehicleModel;
111 import org.opentrafficsim.road.gtu.lane.perception.CategoricalLanePerception;
112 import org.opentrafficsim.road.gtu.lane.perception.LanePerception;
113 import org.opentrafficsim.road.gtu.lane.perception.PerceptionFactory;
114 import org.opentrafficsim.road.gtu.lane.perception.categories.AnticipationTrafficPerception;
115 import org.opentrafficsim.road.gtu.lane.perception.categories.DirectInfrastructurePerception;
116 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.DirectNeighborsPerception;
117 import org.opentrafficsim.road.gtu.lane.perception.categories.neighbors.HeadwayGtuType;
118 import org.opentrafficsim.road.gtu.lane.plan.operational.LaneChange;
119 import org.opentrafficsim.road.gtu.lane.tactical.DesireBased;
120 import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM;
121 import org.opentrafficsim.road.gtu.lane.tactical.following.CarFollowingModelFactory;
122 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus;
123 import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
124 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.AccelerationIncentive;
125 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveKeep;
126 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveRoute;
127 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSocioSpeed;
128 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveSpeedWithCourtesy;
129 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.IncentiveStayRight;
130 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory;
131 import org.opentrafficsim.road.gtu.lane.tactical.lmrs.SocioDesiredSpeed;
132 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
133 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
134 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Incentive;
135 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.LmrsParameters;
136 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.MandatoryIncentive;
137 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
138 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Tailgating;
139 import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.VoluntaryIncentive;
140 import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory;
141 import org.opentrafficsim.road.gtu.strategical.od.Categorization;
142 import org.opentrafficsim.road.gtu.strategical.od.Category;
143 import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
144 import org.opentrafficsim.road.gtu.strategical.od.ODMatrix;
145 import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory;
146 import org.opentrafficsim.road.network.OTSRoadNetwork;
147 import org.opentrafficsim.road.network.lane.CrossSectionLink;
148 import org.opentrafficsim.road.network.lane.DirectedLanePosition;
149 import org.opentrafficsim.road.network.lane.Lane;
150 import org.opentrafficsim.road.network.lane.LaneType;
151 import org.opentrafficsim.road.network.lane.OTSRoadNode;
152 import org.opentrafficsim.road.network.lane.Stripe;
153 import org.opentrafficsim.road.network.lane.Stripe.Permeable;
154 import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
155 import org.opentrafficsim.road.network.lane.object.SpeedSign;
156 import org.opentrafficsim.road.network.lane.object.sensor.Detector;
157 import org.opentrafficsim.road.network.lane.object.sensor.Detector.CompressionMethod;
158 import org.opentrafficsim.road.network.lane.object.sensor.Detector.DetectorMeasurement;
159 import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
160 import org.opentrafficsim.road.network.sampling.GtuData;
161 import org.opentrafficsim.road.network.sampling.LaneData;
162 import org.opentrafficsim.road.network.sampling.RoadSampler;
163 import org.opentrafficsim.swing.gui.AnimationToggles;
164 import org.opentrafficsim.swing.gui.OTSAnimationPanel;
165 import org.opentrafficsim.swing.gui.OTSSimulationApplication;
166 
167 import nl.tudelft.simulation.dsol.SimRuntimeException;
168 import nl.tudelft.simulation.dsol.experiment.Replication;
169 import nl.tudelft.simulation.dsol.simulators.DEVSSimulatorInterface;
170 import nl.tudelft.simulation.jstats.distributions.DistLogNormal;
171 import nl.tudelft.simulation.jstats.distributions.DistNormal;
172 import nl.tudelft.simulation.jstats.distributions.DistTriangular;
173 import nl.tudelft.simulation.jstats.streams.MersenneTwister;
174 import nl.tudelft.simulation.jstats.streams.StreamInterface;
175 
176 /**
177  * Simulations regarding LMRS lane change strategies. This entails the base LMRS with:
178  * <ul>
179  * <li>Distributed Tmax</li>
180  * <li>Distributed vGain</li>
181  * <li>Distributed socio-speed sensitivity parameter (LmrsParameters.SOCIO)</li>
182  * <li>Altered gap-acceptance: use own Tmax (GapAcceptance.EGO_HEADWAY) [not required if Tmin/max not distributed]</li>
183  * <li>Altered desired speed: increase during overtaking (SocioDesiredSpeed)</li>
184  * <li>Lane change incentive to get out of the way (IncentiveSocioSpeed)</li>
185  * </ul>
186  * <p>
187  * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
188  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
189  * <p>
190  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 2 mrt. 2018 <br>
191  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
192  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
193  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
194  */
195 public class LmrsStrategies implements EventListenerInterface
196 {
197 
198     /** */
199     private static final long serialVersionUID = 20200516L;
200 
201     /** Simulation time. */
202     static final Time SIMTIME = Time.instantiateSI(3900);
203 
204     /** Truck fraction. */
205     private double fTruck;
206 
207     /** Synchronization. */
208     static final Synchronization SYNCHRONIZATION = Synchronization.PASSIVE;
209 
210     /** Cooperation. */
211     static final Cooperation COOPERATION = Cooperation.PASSIVE;
212 
213     /** Gap-acceptance. */
214     static final GapAcceptance GAPACCEPTANCE = GapAcceptance.INFORMED;
215 
216     /** Use base LMRS. */
217     private boolean baseLMRS;
218 
219     /** Form of tailgating. */
220     private Tailgating tailgating;
221 
222     /** Seed. */
223     private long seed;
224 
225     /** Sigma. */
226     private double sigma;
227 
228     /** vGain [km/h] (after log-normal shift). */
229     private double vGain;
230 
231     /** Maximum headway [s]. */
232     private double tMax;
233 
234     /** Maximum flow [veh/h]. */
235     private double qMax;
236 
237     /** Suffix for file name. */
238     private String suffix;
239 
240     /** Folder to save files. */
241     private String folder;
242 
243     /** Strategical planner factories per GTU type. */
244     private final Map<GTUType, LaneBasedStrategicalPlannerFactory<?>> factories = new LinkedHashMap<>();
245 
246     /** The simulator. */
247     private DEVSSimulatorInterface.TimeDoubleUnit simulator;
248 
249     /** The network. */
250     private OTSRoadNetwork network;
251 
252     /** Autorun. */
253     private boolean autorun;
254 
255     /** List of lane changes. */
256     private List<String> laneChanges = new ArrayList<>();
257 
258     /** Sample data or not. */
259     private boolean sampling;
260 
261     /** Sampler when sampling. */
262     private Sampler<GtuData> sampler;
263 
264     /** GTU colorer. */
265     private static final GTUColorer colorer = SwitchableGTUColorer.builder().addActiveColorer(new FixedColor(Color.BLUE,
266         "Blue")).addColorer(GTUTypeColorer.DEFAULT).addColorer(new IDGTUColorer()).addColorer(new SpeedGTUColorer(new Speed(150,
267             SpeedUnit.KM_PER_HOUR))).addColorer(new DesiredSpeedColorer(new Speed(80, SpeedUnit.KM_PER_HOUR), new Speed(150,
268                 SpeedUnit.KM_PER_HOUR))).addColorer(new AccelerationGTUColorer(Acceleration.instantiateSI(-6.0), Acceleration
269                     .instantiateSI(2))).addColorer(new SynchronizationColorer()).addColorer(new DesiredHeadwayColorer(Duration
270                         .instantiateSI(0.5), Duration.instantiateSI(2.0))).addColorer(new TotalDesireColorer()).addColorer(
271                             new IncentiveColorer(IncentiveRoute.class)).addColorer(new IncentiveColorer(
272                                 IncentiveStayRight.class)).addColorer(new IncentiveColorer(IncentiveSpeedWithCourtesy.class))
273         .addColorer(new IncentiveColorer(IncentiveKeep.class)).addColorer(new IncentiveColorer(IncentiveSocioSpeed.class))
274         .addColorer(new SocialPressureColorer()).build();
275 
276     /**
277      * Main method with command line arguments.
278      * @param args String[]; String[] command line arguments
279      */
280     @SuppressWarnings("unchecked")
281     public static void main(final String[] args)
282     {
283         LaneChange.MIN_LC_LENGTH_FACTOR = 1.0;
284 
285         // default properties
286         boolean autorun = false;
287         String suffix = "";
288         long seed = 1L;
289         double sigma = 0.1; // 0.25;
290         double vGain = 3.3789;
291         // 25km/h -> 3.3789
292         // 35km/h -> 3.7153
293         // 50km/h -> 4.072
294         // 70km/h -> 4.4085
295         // base: 69.6km/h
296         boolean baseLMRS = false;
297         double tMax = 1.6;
298         double fTruck = 0.1;
299         double qMax = 5500;
300         String folder = "D:/";
301         boolean sampling = false;
302         Tailgating tailgating = Tailgating.PRESSURE;
303 
304         boolean vGainSet = false;
305 
306         // parse args
307         for (String arg : args)
308         {
309             int equalsPos = arg.indexOf("=");
310             if (equalsPos >= 0)
311             {
312                 // set something
313                 String key = arg.substring(0, equalsPos);
314                 String value = arg.substring(equalsPos + 1);
315                 if ("autorun".equalsIgnoreCase(key))
316                 {
317                     autorun = Boolean.parseBoolean(value);
318                 }
319                 else if ("suffix".equalsIgnoreCase(key))
320                 {
321                     suffix = value;
322                 }
323                 else if ("seed".equalsIgnoreCase(key))
324                 {
325                     seed = Long.parseLong(value);
326                 }
327                 else if ("sigma".equalsIgnoreCase(key))
328                 {
329                     sigma = Double.parseDouble(value);
330                 }
331                 else if ("vgain".equalsIgnoreCase(key))
332                 {
333                     vGain = Double.parseDouble(value);
334                     vGainSet = true;
335                 }
336                 else if ("baselmrs".equalsIgnoreCase(key))
337                 {
338                     baseLMRS = Boolean.parseBoolean(value);
339                     if (baseLMRS && !vGainSet)
340                     {
341                         vGain = Try.assign(() -> LmrsParameters.VGAIN.getDefaultValue().getInUnit(SpeedUnit.KM_PER_HOUR), "");
342                     }
343                 }
344                 else if ("tmax".equalsIgnoreCase(key))
345                 {
346                     tMax = Double.parseDouble(value);
347                 }
348                 else if ("ftruck".equalsIgnoreCase(key))
349                 {
350                     fTruck = Double.parseDouble(value);
351                 }
352                 else if ("qmax".equalsIgnoreCase(key))
353                 {
354                     qMax = Double.parseDouble(value);
355                 }
356                 else if ("folder".equalsIgnoreCase(key))
357                 {
358                     folder = value;
359                 }
360                 else if ("sampling".equalsIgnoreCase(key))
361                 {
362                     sampling = Boolean.parseBoolean(value);
363                 }
364                 else if ("tailgating".equalsIgnoreCase(key))
365                 {
366                     // overrule for sensitivity analysis
367                     tailgating = value.equalsIgnoreCase("none") ? Tailgating.NONE : (value.equalsIgnoreCase("pressure")
368                             ? Tailgating.PRESSURE : Tailgating.RHO_ONLY);
369                 }
370                 else
371                 {
372                     throw new RuntimeException("Key " + key + " not supported.");
373                 }
374             }
375         }
376         Throw.whenNull(folder, "Provide a folder to save files using a command line argument named 'folder'.");
377 
378         // setup arguments
379         LmrsStrategiesrategies lmrsStrategies = new LmrsStrategies();
380         lmrsStrategies.autorun = autorun;
381         lmrsStrategies.suffix = suffix;
382         lmrsStrategies.seed = seed;
383         lmrsStrategies.sigma = sigma;
384         lmrsStrategies.vGain = vGain;
385         lmrsStrategies.baseLMRS = baseLMRS;
386         lmrsStrategies.tailgating = tailgating;
387         lmrsStrategies.tMax = tMax;
388         lmrsStrategies.fTruck = fTruck;
389         lmrsStrategies.qMax = qMax;
390         lmrsStrategies.folder = folder;
391         lmrsStrategies.sampling = sampling;
392         if (baseLMRS)
393         {
394             lmrsStrategies.incentives = new Class[] {IncentiveRoute.class, IncentiveSpeedWithCourtesy.class,
395                 IncentiveKeep.class};
396         }
397         else
398         {
399             lmrsStrategies.incentives = new Class[] {IncentiveRoute.class, IncentiveSpeedWithCourtesy.class,
400                 IncentiveKeep.class, IncentiveSocioSpeed.class};
401         }
402 
403         // run
404         if (autorun)
405         {
406             try
407             {
408                 OTSSimulator simulator = new OTSSimulator("LmrsStrategies");
409                 final LmrsStrategiesModel lmrsModel = lmrsStrategies.new LmrsStrategiesModel(simulator);
410                 // + 1e-9 is a hack to allow step() to perform detector aggregation of more than 1 detectors -at- the sim end
411                 simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(SIMTIME.si + 1e-9), lmrsModel);
412                 lmrsStrategies.new LmrsStrategiesSimulation(lmrsModel);
413                 double tReport = 60.0;
414                 Time t = simulator.getSimulatorTime();
415                 while (t.le(SIMTIME))
416                 {
417                     simulator.step();
418                     t = simulator.getSimulatorTime();
419                     if (t.si >= tReport)
420                     {
421                         System.out.println("Simulation time is " + t);
422                         tReport += 60.0;
423                     }
424                 }
425                 simulator.stop(); // end of simulation event
426             }
427             catch (Exception exception)
428             {
429                 exception.printStackTrace();
430                 System.exit(-1);
431             }
432         }
433         else
434         {
435             try
436             {
437                 OTSAnimator simulator = new OTSAnimator("LmrsStrategies");
438                 final LmrsStrategiesModel lmrsModel = lmrsStrategies.new LmrsStrategiesModel(simulator);
439                 // + 1e-9 is a hack to allow step() to perform detector aggregation of more than 1 detectors -at- the sim end
440                 simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(SIMTIME.si + 1e-9), lmrsModel);
441                 OTSAnimationPanel animationPanel = new OTSAnimationPanel(lmrsModel.getNetwork().getExtent(), new Dimension(800,
442                     600), simulator, lmrsModel, LmrsStrategies.colorer, lmrsModel.getNetwork());
443                 lmrsStrategies.new LmrsStrategiesAnimation(lmrsModel, animationPanel);
444             }
445             catch (Exception exception)
446             {
447                 exception.printStackTrace();
448             }
449         }
450     }
451 
452     /**
453      * Simulation without visualization.
454      * <p>
455      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
456      * <br>
457      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
458      * <p>
459      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 21 mrt. 2018 <br>
460      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
461      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
462      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
463      */
464     class LmrsStrategiesSimulation extends AbstractOTSSimulationApplication
465     {
466         /** */
467         private static final long serialVersionUID = 1L;
468 
469         /**
470          * @param model OTSModelInterface; model
471          */
472         LmrsStrategiesSimulation(final OTSModelInterface model)
473         {
474             super(model);
475         }
476     }
477 
478     /**
479      * Animator.
480      * <p>
481      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
482      * <br>
483      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
484      * <p>
485      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mrt. 2018 <br>
486      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
487      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
488      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
489      */
490     class LmrsStrategiesAnimation extends OTSSimulationApplication<OTSModelInterface>
491     {
492         /** */
493         private static final long serialVersionUID = 20180303L;
494 
495         /**
496          * @param model OTSModelInterface; the model
497          * @param panel OTSAnimationPanel; the animation panel
498          * @throws OTSDrawingException on animation error
499          */
500         LmrsStrategiesAnimation(final OTSModelInterface model, final OTSAnimationPanel panel) throws OTSDrawingException
501         {
502             super(model, panel);
503         }
504 
505         /** {@inheritDoc} */
506         @Override
507         protected void setAnimationToggles()
508         {
509             AnimationToggles.setIconAnimationTogglesFull(getAnimationPanel());
510             getAnimationPanel().getAnimationPanel().toggleClass(OTSLink.class);
511             getAnimationPanel().getAnimationPanel().toggleClass(OTSNode.class);
512             getAnimationPanel().getAnimationPanel().toggleClass(GtuGeneratorQueue.class);
513             getAnimationPanel().getAnimationPanel().showClass(SpeedSign.class);
514         }
515 
516     }
517 
518     /**
519      * LMRS model.
520      * <p>
521      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
522      * <br>
523      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
524      * <p>
525      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mrt. 2018 <br>
526      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
527      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
528      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
529      */
530     class LmrsStrategiesModel extends AbstractOTSModel
531     {
532         /**
533          * @param simulator OTSSimulatorInterface; the simulator
534          */
535         LmrsStrategiesModel(final OTSSimulatorInterface simulator)
536         {
537             super(simulator);
538         }
539 
540         /** */
541         private static final long serialVersionUID = 20180303L;
542 
543         /** {@inheritDoc} */
544         @Override
545         @SuppressWarnings({"synthetic-access", "checkstyle:methodlength"})
546         public void constructModel()
547         {
548             LmrsStrategies.this.simulator = getSimulator();
549             OTSRoadNetwork net = new OTSRoadNetwork("LMRS strategies", true, getSimulator());
550             try
551             {
552                 LmrsStrategies.this.simulator.addListener(LmrsStrategies.this, Replication.END_REPLICATION_EVENT);
553             }
554             catch (RemoteException exception1)
555             {
556                 exception1.printStackTrace();
557             }
558             LmrsStrategies.this.network = net;
559             net.addListener(LmrsStrategies.this, Network.GTU_ADD_EVENT);
560             net.addListener(LmrsStrategies.this, Network.GTU_REMOVE_EVENT);
561             Map<String, StreamInterface> streams = new LinkedHashMap<>();
562             StreamInterface stream = new MersenneTwister(LmrsStrategies.this.seed);
563             streams.put("generation", stream);
564             getSimulator().getReplication().setStreams(streams);
565 
566             // Vehicle-driver classes
567             // characteristics generator using the input available in this context
568             /** Characteristics generator. */
569             class LmrsStrategyCharacteristicsGenerator implements GTUCharacteristicsGeneratorOD
570             {
571 
572                 /** Distributed maximum speed for trucks. */
573                 private ContinuousDistDoubleScalar.Rel<Speed, SpeedUnit> vTruck;
574 
575                 /**
576                  * Constructor.
577                  * @param strm StreamInterface;
578                  */
579                 LmrsStrategyCharacteristicsGenerator(final StreamInterface strm)
580                 {
581                     this.vTruck = new ContinuousDistDoubleScalar.Rel<>(new DistNormal(strm, 85.0, 2.5), SpeedUnit.KM_PER_HOUR);
582                 }
583 
584                 /** {@inheritDoc} */
585                 @Override
586                 public LaneBasedGTUCharacteristics draw(final Node origin, final Node destination, final Category category,
587                         final StreamInterface randomStream) throws GTUException
588                 {
589                     GTUType gtuType = category.get(GTUType.class);
590                     GTUCharacteristics gtuCharacteristics = Try.assign(() -> GTUType.defaultCharacteristics(gtuType,
591                         LmrsStrategies.this.network, randomStream), "Exception while applying default GTU characteristics.");
592                     if (gtuType.equals(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.TRUCK)))
593                     {
594                         gtuCharacteristics = new GTUCharacteristics(LmrsStrategies.this.network.getGtuType(
595                             GTUType.DEFAULTS.TRUCK), gtuCharacteristics.getLength(), gtuCharacteristics.getWidth(), this.vTruck
596                                 .draw(), gtuCharacteristics.getMaximumAcceleration(), gtuCharacteristics
597                                     .getMaximumDeceleration(), gtuCharacteristics.getFront());
598                     }
599                     return new LaneBasedGTUCharacteristics(gtuCharacteristics, LmrsStrategies.this.factories.get(gtuType), null,
600                         origin, destination, VehicleModel.NONE);
601                 }
602             }
603             /** Perception factory. */
604             class LmrsStrategiesPerceptionFactory implements PerceptionFactory
605             {
606                 /** {@inheritDoc} */
607                 @Override
608                 public LanePerception generatePerception(final LaneBasedGTU gtu)
609                 {
610                     LanePerception perception = new CategoricalLanePerception(gtu);
611                     perception.addPerceptionCategory(new DirectEgoPerception<>(perception));
612                     perception.addPerceptionCategory(new DirectInfrastructurePerception(perception));
613                     perception.addPerceptionCategory(new DirectNeighborsPerception(perception, HeadwayGtuType.WRAP));
614                     perception.addPerceptionCategory(new AnticipationTrafficPerception(perception));
615                     return perception;
616                 }
617 
618                 /** {@inheritDoc} */
619                 @Override
620                 public Parameters getParameters() throws ParameterException
621                 {
622                     return new ParameterSet().setDefaultParameter(ParameterTypes.LOOKAHEAD).setDefaultParameter(
623                         ParameterTypes.LOOKBACKOLD).setDefaultParameter(ParameterTypes.PERCEPTION).setDefaultParameter(
624                             ParameterTypes.LOOKBACK);
625                 }
626             }
627             PerceptionFactory perceptionFactory = new LmrsStrategiesPerceptionFactory();
628             /** IDM factory with socio speed. */
629             class SocioIDMFactory implements CarFollowingModelFactory<IDMPlus>
630             {
631                 /** {@inheritDoc} */
632                 @Override
633                 public Parameters getParameters() throws ParameterException
634                 {
635                     ParameterSet parameters = new ParameterSet();
636                     parameters.setDefaultParameters(AbstractIDM.class);
637                     return parameters;
638                 }
639 
640                 /** {@inheritDoc} */
641                 @Override
642                 public IDMPlus generateCarFollowingModel()
643                 {
644                     return new IDMPlus(AbstractIDM.HEADWAY, new SocioDesiredSpeed(AbstractIDM.DESIRED_SPEED));
645                 }
646             }
647             // random parameters
648             ParameterFactoryByType parameterFactory = new ParameterFactoryByType();
649             parameterFactory.addParameter(Tailgating.RHO, 0.0);
650             if (!LmrsStrategies.this.baseLMRS)
651             {
652                 parameterFactory.addParameter(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.CAR),
653                     LmrsParameters.SOCIO, new DistTriangular(stream, 0.0, LmrsStrategies.this.sigma, 1.0));
654                 parameterFactory.addCorrelation(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.CAR), null,
655                     LmrsParameters.SOCIO, (first, then) -> then <= 1.0 ? then : 1.0);
656                 parameterFactory.addParameter(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.TRUCK),
657                     LmrsParameters.SOCIO, 1.0);
658                 parameterFactory.addParameter(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.CAR),
659                     LmrsParameters.VGAIN, new ContinuousDistSpeed(new DistLogNormal(stream, LmrsStrategies.this.vGain, 0.4),
660                         SpeedUnit.KM_PER_HOUR));
661                 parameterFactory.addParameter(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.TRUCK),
662                     LmrsParameters.VGAIN, new Speed(50.0, SpeedUnit.KM_PER_HOUR));
663                 parameterFactory.addParameter(ParameterTypes.TMAX, Duration.instantiateSI(LmrsStrategies.this.tMax));
664             }
665             else
666             {
667                 // overrule for sensitivity analysis
668                 parameterFactory.addParameter(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.CAR),
669                     LmrsParameters.VGAIN, new Speed(LmrsStrategies.this.vGain, SpeedUnit.KM_PER_HOUR));
670             }
671             parameterFactory.addParameter(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.CAR), ParameterTypes.FSPEED,
672                 new DistNormal(stream, 123.7 / 120.0, 12.0 / 120.0));
673             parameterFactory.addParameter(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.TRUCK), ParameterTypes.A,
674                 Acceleration.instantiateSI(0.4));
675             parameterFactory.addParameter(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.TRUCK), ParameterTypes.FSPEED,
676                 1.0);
677 
678             try
679             {
680                 // Strategical factories
681                 for (GTUType gtuType : new GTUType[] {LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.CAR),
682                     LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.TRUCK)})
683                 {
684                     // incentives
685                     Set<MandatoryIncentive> mandatoryIncentives = new LinkedHashSet<>();
686                     Set<VoluntaryIncentive> voluntaryIncentives = new LinkedHashSet<>();
687                     Set<AccelerationIncentive> accelerationIncentives = new LinkedHashSet<>();
688                     mandatoryIncentives.add(new IncentiveRoute());
689                     voluntaryIncentives.add(new IncentiveSpeedWithCourtesy());
690                     voluntaryIncentives.add(new IncentiveKeep()); // before socio-speed and stay-right
691                     if (!LmrsStrategies.this.baseLMRS)
692                     {
693                         voluntaryIncentives.add(new IncentiveSocioSpeed());
694                     }
695                     // accelerationIncentives.add(new AccelerationNoRightOvertake());
696                     if (gtuType.equals(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.TRUCK)))
697                     {
698                         voluntaryIncentives.add(new IncentiveStayRight());
699                     }
700                     // car-following factory
701                     CarFollowingModelFactory<?> cfFactory = // trucks don't change their desired speed
702                             gtuType.equals(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.CAR))
703                                 && !LmrsStrategies.this.baseLMRS ? new SocioIDMFactory() : new IDMPlusFactory(stream);
704                     // tailgating
705                     Tailgating tlgt = LmrsStrategies.this.baseLMRS ? Tailgating.NONE : LmrsStrategies.this.tailgating;
706                     // strategical and tactical factory
707                     LaneBasedStrategicalPlannerFactory<?> laneBasedStrategicalPlannerFactory =
708                             new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactory(cfFactory, perceptionFactory,
709                                 SYNCHRONIZATION, COOPERATION, GAPACCEPTANCE, tlgt, mandatoryIncentives, voluntaryIncentives,
710                                 accelerationIncentives), parameterFactory);
711                     LmrsStrategies.this.factories.put(gtuType, laneBasedStrategicalPlannerFactory);
712                 }
713 
714                 // Network
715                 OTSPoint3D pointA = new OTSPoint3D(0, 0, 0);
716                 OTSPoint3D pointB = new OTSPoint3D(4000, 0, 0);
717                 OTSPoint3D pointC = new OTSPoint3D(7400, 0, 0);
718                 OTSRoadNode nodeA = new OTSRoadNode(net, "A", pointA, Direction.ZERO);
719                 OTSRoadNode nodeB = new OTSRoadNode(net, "B", pointB, Direction.ZERO);
720                 OTSRoadNode nodeC = new OTSRoadNode(net, "C", pointC, Direction.ZERO);
721                 CrossSectionLink linkAB = new CrossSectionLink(net, "AB", nodeA, nodeB, LmrsStrategies.this.network.getLinkType(
722                     LinkType.DEFAULTS.FREEWAY), new OTSLine3D(pointA, pointB), LaneKeepingPolicy.KEEPRIGHT);
723                 CrossSectionLink linkBC = new CrossSectionLink(net, "BC", nodeB, nodeC, LmrsStrategies.this.network.getLinkType(
724                     LinkType.DEFAULTS.FREEWAY), new OTSLine3D(pointB, pointC), LaneKeepingPolicy.KEEPRIGHT);
725                 Lane laneAB1 = new Lane(linkAB, "laneAB1", Length.instantiateSI(0.0), Length.instantiateSI(3.5),
726                     LmrsStrategies.this.network.getLaneType(LaneType.DEFAULTS.HIGHWAY), new Speed(120, SpeedUnit.KM_PER_HOUR));
727                 Lane laneAB2 = new Lane(linkAB, "laneAB2", Length.instantiateSI(3.5), Length.instantiateSI(3.5),
728                     LmrsStrategies.this.network.getLaneType(LaneType.DEFAULTS.HIGHWAY), new Speed(120, SpeedUnit.KM_PER_HOUR));
729                 Lane laneAB3 = new Lane(linkAB, "laneAB3", Length.instantiateSI(7.0), Length.instantiateSI(3.5),
730                     LmrsStrategies.this.network.getLaneType(LaneType.DEFAULTS.HIGHWAY), new Speed(120, SpeedUnit.KM_PER_HOUR));
731                 Lane laneBC1 = new Lane(linkBC, "laneBC1", Length.instantiateSI(0.0), Length.instantiateSI(3.5),
732                     LmrsStrategies.this.network.getLaneType(LaneType.DEFAULTS.HIGHWAY), new Speed(120, SpeedUnit.KM_PER_HOUR));
733                 Lane laneBC2 = new Lane(linkBC, "laneBC2", Length.instantiateSI(3.5), Length.instantiateSI(3.5),
734                     LmrsStrategies.this.network.getLaneType(LaneType.DEFAULTS.HIGHWAY), new Speed(120, SpeedUnit.KM_PER_HOUR));
735                 Set<GTUType> gtuTypes = new LinkedHashSet<>();
736                 gtuTypes.add(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.VEHICLE));
737                 Stripe stripeAB1 = new Stripe(linkAB, Length.instantiateSI(-1.75), Length.instantiateSI(-1.75), Length
738                     .instantiateSI(0.2));
739                 Stripe stripeAB2 = new Stripe(linkAB, Length.instantiateSI(1.75), Length.instantiateSI(1.75), Length
740                     .instantiateSI(0.2), gtuTypes, Permeable.BOTH);
741                 Stripe stripeAB3 = new Stripe(linkAB, Length.instantiateSI(5.25), Length.instantiateSI(5.25), Length
742                     .instantiateSI(0.2), gtuTypes, Permeable.BOTH);
743                 Stripe stripeAB4 = new Stripe(linkAB, Length.instantiateSI(8.75), Length.instantiateSI(8.75), Length
744                     .instantiateSI(0.2), gtuTypes, Permeable.BOTH);
745                 Stripe stripeBC1 = new Stripe(linkBC, Length.instantiateSI(-1.75), Length.instantiateSI(-1.75), Length
746                     .instantiateSI(0.2), gtuTypes, Permeable.BOTH);
747                 Stripe stripeBC2 = new Stripe(linkBC, Length.instantiateSI(1.75), Length.instantiateSI(1.75), Length
748                     .instantiateSI(0.2), gtuTypes, Permeable.BOTH);
749                 Stripe stripeBC3 = new Stripe(linkBC, Length.instantiateSI(5.25), Length.instantiateSI(5.25), Length
750                     .instantiateSI(0.2), gtuTypes, Permeable.BOTH);
751                 new NodeAnimation(nodeA, getSimulator());
752                 new NodeAnimation(nodeB, getSimulator());
753                 new NodeAnimation(nodeC, getSimulator());
754                 new LinkAnimation(linkAB, getSimulator(), 0.5f);
755                 new LinkAnimation(linkBC, getSimulator(), 0.5f);
756                 new LaneAnimation(laneAB1, getSimulator(), Color.GRAY.brighter());
757                 new LaneAnimation(laneAB2, getSimulator(), Color.GRAY.brighter());
758                 new LaneAnimation(laneAB3, getSimulator(), Color.GRAY.brighter());
759                 new LaneAnimation(laneBC1, getSimulator(), Color.GRAY.brighter());
760                 new LaneAnimation(laneBC2, getSimulator(), Color.GRAY.brighter());
761                 new StripeAnimation(stripeAB1, getSimulator(), TYPE.SOLID);
762                 new StripeAnimation(stripeAB2, getSimulator(), TYPE.DASHED);
763                 new StripeAnimation(stripeAB3, getSimulator(), TYPE.DASHED);
764                 new StripeAnimation(stripeAB4, getSimulator(), TYPE.SOLID);
765                 new StripeAnimation(stripeBC1, getSimulator(), TYPE.SOLID);
766                 new StripeAnimation(stripeBC2, getSimulator(), TYPE.DASHED);
767                 new StripeAnimation(stripeBC3, getSimulator(), TYPE.SOLID);
768                 // sensors
769                 new SinkSensor(laneBC1, laneBC1.getLength().minus(Length.instantiateSI(100.0)), Compatible.EVERYTHING,
770                     getSimulator());
771                 new SinkSensor(laneBC2, laneBC2.getLength().minus(Length.instantiateSI(100.0)), Compatible.EVERYTHING,
772                     getSimulator());
773 
774                 // detectors
775                 Lane[][] grid = new Lane[][] {new Lane[] {laneAB3}, new Lane[] {laneAB2, laneBC2}, new Lane[] {laneAB1,
776                     laneBC1}};
777                 Duration aggregationPeriod = Duration.instantiateSI(60.0);
778                 DetectorMeasurement<?, ?>[] measurements = new DetectorMeasurement[] {Detector.MEAN_SPEED, Detector.PASSAGES,
779                     new VGainMeasurement(), new SigmaMeasurement(), new VDesMeasurement(), new VDes0Measurement()};
780                 String[] prefix = {"A", "B", "C"};
781                 for (int i = 0; i < grid.length; i++)
782                 {
783                     int num = 1;
784                     Length pos = Length.instantiateSI(100.0);
785                     for (int j = 0; j < grid[i].length; j++)
786                     {
787                         while (pos.lt(grid[i][j].getLength()))
788                         {
789                             new Detector(String.format("%s%02d", prefix[i], num), grid[i][j], pos, Length.ZERO,
790                                 LmrsStrategies.this.simulator, aggregationPeriod, measurements);
791                             num++;
792                             pos = pos.plus(Length.instantiateSI(100.0));
793                         }
794                         pos = pos.minus(grid[i][j].getLength());
795                     }
796                 }
797 
798                 // OD
799                 Categorization categorization = new Categorization("ODExample", GTUType.class);
800                 List<Node> origins = new ArrayList<>();
801                 origins.add(nodeA);
802                 List<Node> destinations = new ArrayList<>();
803                 destinations.add(nodeC);
804                 TimeVector timeVector = DoubleVector.instantiate(new double[] {0.0, 300.0, 2700.0, SIMTIME.si},
805                     TimeUnit.DEFAULT, StorageType.DENSE);
806                 ODMatrix od = new ODMatrix("LMRS strategies", origins, destinations, categorization, timeVector,
807                     Interpolation.LINEAR);
808                 double q = LmrsStrategies.this.qMax;
809                 FrequencyVector demand = DoubleVector.instantiate(new double[] {q * .6, q * .6, q, 0.0}, FrequencyUnit.PER_HOUR,
810                     StorageType.DENSE);
811                 Category category = new Category(categorization, LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.CAR));
812                 od.putDemandVector(nodeA, nodeC, category, demand, timeVector, Interpolation.LINEAR, 1.0
813                     - LmrsStrategies.this.fTruck);
814                 category = new Category(categorization, LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.TRUCK));
815                 od.putDemandVector(nodeA, nodeC, category, demand, timeVector, Interpolation.LINEAR,
816                     LmrsStrategies.this.fTruck);
817                 // options
818                 MarkovCorrelation<GTUType, Frequency> markov = new MarkovCorrelation<>();
819                 markov.addState(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.TRUCK), 0.4);
820                 LaneBiases biases = new LaneBiases().addBias(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.VEHICLE),
821                     LaneBias.bySpeed(140, 100)).addBias(LmrsStrategies.this.network.getGtuType(GTUType.DEFAULTS.TRUCK),
822                         LaneBias.TRUCK_RIGHT);
823                 ODOptions odOptions = new ODOptions().set(ODOptions.MARKOV, markov).set(ODOptions.getLaneBiasOption(
824                     LmrsStrategies.this.network), biases).set(ODOptions.NO_LC_DIST, Length.instantiateSI(100.0)).set(
825                         ODOptions.INSTANT_LC, true).set(ODOptions.GTU_TYPE, new LmrsStrategyCharacteristicsGenerator(stream))
826                     .set(ODOptions.HEADWAY_DIST, HeadwayDistribution.CONSTANT);
827                 Map<String, GeneratorObjects> generatedObjects = ODApplier.applyOD(net, od, odOptions);
828                 for (String str : generatedObjects.keySet())
829                 {
830                     new GtuGeneratorQueueAnimation(generatedObjects.get(str).getGenerator(), getSimulator());
831                 }
832 
833                 // Sampler
834                 if (LmrsStrategies.this.sampling)
835                 {
836                     LmrsStrategies.this.sampler = RoadSampler.build(LmrsStrategies.this.network).registerExtendedDataType(
837                         new ExtendedDataTypeLength<GtuData>("Length")
838                         {
839                             @Override
840                             public FloatLength getValue(final GtuData gtu)
841                             {
842                                 return FloatLength.instantiateSI((float) gtu.getGtu().getLength().si);
843                             }
844                         }).registerExtendedDataType(new ExtendedDataTypeNumber<GtuData>("Rho")
845                         {
846                             @Override
847                             public Float getValue(final GtuData gtu)
848                             {
849                                 try
850                                 {
851                                     return gtu.getGtu().getParameters().getParameter(Tailgating.RHO).floatValue();
852                                 }
853                                 catch (ParameterException exception)
854                                 {
855                                     throw new RuntimeException("Could not obtain rho for trajectory.", exception);
856                                 }
857                             }
858                         }).registerExtendedDataType(new ExtendedDataTypeSpeed<GtuData>("V0")
859                         {
860                             @Override
861                             public FloatSpeed getValue(final GtuData gtu)
862                             {
863                                 try
864                                 {
865                                     return FloatSpeed.instantiateSI(gtu.getGtu().getDesiredSpeed().floatValue());
866                                 }
867                                 catch (NullPointerException ex)
868                                 {
869                                     return FloatSpeed.NaN;
870                                 }
871                             }
872                         }).registerExtendedDataType(new ExtendedDataTypeDuration<GtuData>("T")
873                         {
874                             @Override
875                             public FloatDuration getValue(final GtuData gtu)
876                             {
877                                 try
878                                 {
879                                     return FloatDuration.instantiateSI(gtu.getGtu().getParameters().getParameter(
880                                         ParameterTypes.T).floatValue());
881                                 }
882                                 catch (ParameterException exception)
883                                 {
884                                     throw new RuntimeException("Could not obtain T for trajectory.", exception);
885                                 }
886                             }
887                         }).create();
888 
889                     addLaneToSampler(laneAB1);
890                     addLaneToSampler(laneAB2);
891                     addLaneToSampler(laneAB3);
892                     addLaneToSampler(laneBC1);
893                     addLaneToSampler(laneBC2);
894 
895                 }
896             }
897             catch (NetworkException | OTSGeometryException | NamingException | ValueRuntimeException | ParameterException
898                 | RemoteException | SimRuntimeException exception)
899             {
900                 exception.printStackTrace();
901             }
902         }
903 
904         /**
905          * Adds a lane to the sampler.
906          * @param lane Lane; lane
907          */
908         @SuppressWarnings("synthetic-access")
909         private void addLaneToSampler(final Lane lane)
910         {
911             LmrsStrategies.this.sampler.registerSpaceTimeRegion(new SpaceTimeRegion(new KpiLaneDirection(new LaneData(lane),
912                 KpiGtuDirectionality.DIR_PLUS), Length.ZERO, lane.getLength(), Time.instantiateSI(300), SIMTIME));
913         }
914 
915         /** {@inheritDoc} */
916         @SuppressWarnings("synthetic-access")
917         @Override
918         public OTSRoadNetwork getNetwork()
919         {
920             return LmrsStrategies.this.network;
921         }
922 
923         /** {@inheritDoc} */
924         @Override
925         public Serializable getSourceId()
926         {
927             return "LmrsStrategiesModel";
928         }
929 
930     }
931 
932     /** Incentives. */
933     private Class<? extends Incentive>[] incentives;
934 
935     /** {@inheritDoc} */
936     @Override
937     public void notify(final EventInterface event) throws RemoteException
938     {
939         if (event.getType().equals(LaneBasedGTU.LANE_CHANGE_EVENT))
940         {
941             Object[] payload = (Object[]) event.getContent();
942             GTU gtu = this.network.getGTU((String) payload[0]);
943             LateralDirectionality dir = (LateralDirectionality) payload[1];
944             DirectedLanePosition from = (DirectedLanePosition) payload[2];
945             DesireBased desire = (DesireBased) gtu.getTacticalPlanner();
946             Double dMax = Double.NEGATIVE_INFINITY;
947             String cause = "Unknown";
948             for (Class<? extends Incentive> incentive : this.incentives)
949             {
950                 double d = desire.getLatestDesire(incentive).get(dir);
951                 if (d > dMax)
952                 {
953                     cause = incentive.getSimpleName();
954                     dMax = d;
955                 }
956             }
957             this.laneChanges.add(String.format("%.3f,%s,%.3f,%s,%s", this.simulator.getSimulatorTime().si, from.getLane()
958                 .getFullId(), from.getPosition().si, dir, cause));
959         }
960         else if (event.getType().equals(Network.GTU_ADD_EVENT))
961         {
962             this.network.getGTU((String) event.getContent()).addListener(this, LaneBasedGTU.LANE_CHANGE_EVENT);
963         }
964         else if (event.getType().equals(Network.GTU_REMOVE_EVENT))
965         {
966             this.network.getGTU((String) event.getContent()).removeListener(this, LaneBasedGTU.LANE_CHANGE_EVENT);
967         }
968         else if (event.getType().equals(Replication.END_REPLICATION_EVENT))
969         {
970             CompressionMethod compression = this.autorun ? CompressionMethod.ZIP : CompressionMethod.NONE;
971             // write detector data
972             Detector.writeToFile(this.network, this.folder + "detsAggrData" + LmrsStrategies.this.suffix + ".txt", true, "%.3f",
973                 compression);
974             Detector.writeToFile(this.network, this.folder + "detsMesoData" + LmrsStrategies.this.suffix + ".txt", false,
975                 "%.3f", compression);
976             // write lane change data
977             this.laneChanges.add(0, "t[s],lane,x[m],dir,cause");
978             BufferedWriter bw = CompressedFileWriter.create(this.folder + "laneChanges" + LmrsStrategies.this.suffix + ".txt",
979                 this.autorun);
980             try
981             {
982                 for (String str : this.laneChanges)
983                 {
984                     bw.write(str);
985                     bw.newLine();
986                 }
987             }
988             catch (IOException exception)
989             {
990                 throw new RuntimeException("Could not write to file.", exception);
991             }
992             finally
993             {
994                 try
995                 {
996                     if (bw != null)
997                     {
998                         bw.close();
999                     }
1000                 }
1001                 catch (IOException ex)
1002                 {
1003                     ex.printStackTrace();
1004                 }
1005             }
1006             // write sampler data
1007             if (LmrsStrategies.this.sampling)
1008             {
1009                 LmrsStrategies.this.sampler.getSamplerData().writeToFile(this.folder + "sampled" + LmrsStrategies.this.suffix
1010                     + ".txt");
1011             }
1012             // solve bug that event is fired twice
1013             LmrsStrategies.this.simulator.removeListener(LmrsStrategies.this, Replication.END_REPLICATION_EVENT);
1014             // beep
1015             if (!this.autorun)
1016             {
1017                 Toolkit.getDefaultToolkit().beep();
1018             }
1019             else
1020             {
1021                 System.exit(0);
1022             }
1023         }
1024     }
1025 
1026     /**
1027      * Class to store sigma value.
1028      * <p>
1029      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
1030      * <br>
1031      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
1032      * <p>
1033      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mei 2018 <br>
1034      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
1035      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
1036      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
1037      */
1038     class SigmaMeasurement implements DetectorMeasurement<List<Double>, List<Double>>
1039     {
1040         /** {@inheritDoc} */
1041         @Override
1042         public List<Double> identity()
1043         {
1044             return new ArrayList<>();
1045         }
1046 
1047         /** {@inheritDoc} */
1048         @Override
1049         public List<Double> accumulateEntry(final List<Double> cumulative, final LaneBasedGTU gtu, final Detector loopDetector)
1050         {
1051             Double sig = gtu.getParameters().getParameterOrNull(LmrsParameters.SOCIO);
1052             if (sig == null)
1053             {
1054                 cumulative.add(Double.NaN);
1055             }
1056             else
1057             {
1058                 cumulative.add(sig);
1059             }
1060             return cumulative;
1061         }
1062 
1063         /** {@inheritDoc} */
1064         @Override
1065         public List<Double> accumulateExit(final List<Double> cumulative, final LaneBasedGTU gtu, final Detector loopDetector)
1066         {
1067             return cumulative;
1068         }
1069 
1070         /** {@inheritDoc} */
1071         @Override
1072         public boolean isPeriodic()
1073         {
1074             return false;
1075         }
1076 
1077         /** {@inheritDoc} */
1078         @Override
1079         public List<Double> aggregate(final List<Double> cumulative, final int count, final Duration aggregation)
1080         {
1081             return cumulative;
1082         }
1083 
1084         /** {@inheritDoc} */
1085         @Override
1086         public String getName()
1087         {
1088             return "sigma";
1089         }
1090 
1091         /** {@inheritDoc} */
1092         @Override
1093         public String stringValue(final List<Double> aggregate, final String format)
1094         {
1095             return Detector.printListDouble(aggregate, format);
1096         }
1097     }
1098 
1099     /**
1100      * Class to store vGain value.
1101      * <p>
1102      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
1103      * <br>
1104      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
1105      * <p>
1106      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mei 2018 <br>
1107      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
1108      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
1109      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
1110      */
1111     class VGainMeasurement implements DetectorMeasurement<List<Double>, List<Double>>
1112     {
1113         /** {@inheritDoc} */
1114         @Override
1115         public List<Double> identity()
1116         {
1117             return new ArrayList<>();
1118         }
1119 
1120         /** {@inheritDoc} */
1121         @Override
1122         public List<Double> accumulateEntry(final List<Double> cumulative, final LaneBasedGTU gtu, final Detector loopDetector)
1123         {
1124             Speed vGn = gtu.getParameters().getParameterOrNull(LmrsParameters.VGAIN);
1125             if (vGn == null)
1126             {
1127                 cumulative.add(Double.NaN);
1128             }
1129             else
1130             {
1131                 cumulative.add(vGn.si);
1132             }
1133             return cumulative;
1134         }
1135 
1136         /** {@inheritDoc} */
1137         @Override
1138         public List<Double> accumulateExit(final List<Double> cumulative, final LaneBasedGTU gtu, final Detector loopDetector)
1139         {
1140             return cumulative;
1141         }
1142 
1143         /** {@inheritDoc} */
1144         @Override
1145         public boolean isPeriodic()
1146         {
1147             return false;
1148         }
1149 
1150         /** {@inheritDoc} */
1151         @Override
1152         public List<Double> aggregate(final List<Double> cumulative, final int count, final Duration aggregation)
1153         {
1154             return cumulative;
1155         }
1156 
1157         /** {@inheritDoc} */
1158         @Override
1159         public String getName()
1160         {
1161             return "vGain";
1162         }
1163 
1164         /** {@inheritDoc} */
1165         @Override
1166         public String stringValue(final List<Double> aggregate, final String format)
1167         {
1168             return Detector.printListDouble(aggregate, format);
1169         }
1170     }
1171 
1172     /**
1173      * Class to store vDes value.
1174      * <p>
1175      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
1176      * <br>
1177      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
1178      * <p>
1179      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mei 2018 <br>
1180      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
1181      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
1182      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
1183      */
1184     class VDesMeasurement implements DetectorMeasurement<List<Double>, List<Double>>
1185     {
1186         /** {@inheritDoc} */
1187         @Override
1188         public List<Double> identity()
1189         {
1190             return new ArrayList<>();
1191         }
1192 
1193         /** {@inheritDoc} */
1194         @Override
1195         public List<Double> accumulateEntry(final List<Double> cumulative, final LaneBasedGTU gtu, final Detector loopDetector)
1196         {
1197             Speed vDes = gtu.getDesiredSpeed();
1198             if (vDes == null)
1199             {
1200                 cumulative.add(Double.NaN);
1201             }
1202             else
1203             {
1204                 cumulative.add(vDes.si);
1205             }
1206             return cumulative;
1207         }
1208 
1209         /** {@inheritDoc} */
1210         @Override
1211         public List<Double> accumulateExit(final List<Double> cumulative, final LaneBasedGTU gtu, final Detector loopDetector)
1212         {
1213             return cumulative;
1214         }
1215 
1216         /** {@inheritDoc} */
1217         @Override
1218         public boolean isPeriodic()
1219         {
1220             return false;
1221         }
1222 
1223         /** {@inheritDoc} */
1224         @Override
1225         public List<Double> aggregate(final List<Double> cumulative, final int count, final Duration aggregation)
1226         {
1227             return cumulative;
1228         }
1229 
1230         /** {@inheritDoc} */
1231         @Override
1232         public String getName()
1233         {
1234             return "vDes";
1235         }
1236 
1237         /** {@inheritDoc} */
1238         @Override
1239         public String stringValue(final List<Double> aggregate, final String format)
1240         {
1241             return Detector.printListDouble(aggregate, format);
1242         }
1243     }
1244 
1245     /**
1246      * Class to store vDes value.
1247      * <p>
1248      * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
1249      * <br>
1250      * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
1251      * <p>
1252      * @version $Revision$, $LastChangedDate$, by $Author$, initial version 3 mei 2018 <br>
1253      * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
1254      * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
1255      * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
1256      */
1257     class VDes0Measurement implements DetectorMeasurement<List<Double>, List<Double>>
1258     {
1259         /** {@inheritDoc} */
1260         @Override
1261         public List<Double> identity()
1262         {
1263             return new ArrayList<>();
1264         }
1265 
1266         /** {@inheritDoc} */
1267         @Override
1268         public List<Double> accumulateEntry(final List<Double> cumulative, final LaneBasedGTU gtu, final Detector loopDetector)
1269         {
1270             double vDes0;
1271             try
1272             {
1273                 vDes0 = Math.min(gtu.getMaximumSpeed().si, gtu.getParameters().getParameter(ParameterTypes.FSPEED)
1274                     * loopDetector.getLane().getSpeedLimit(gtu.getGTUType()).si);
1275             }
1276             catch (ParameterException | NetworkException exception)
1277             {
1278                 throw new RuntimeException(exception);
1279             }
1280             cumulative.add(vDes0);
1281             return cumulative;
1282         }
1283 
1284         /** {@inheritDoc} */
1285         @Override
1286         public List<Double> accumulateExit(final List<Double> cumulative, final LaneBasedGTU gtu, final Detector loopDetector)
1287         {
1288             return cumulative;
1289         }
1290 
1291         /** {@inheritDoc} */
1292         @Override
1293         public boolean isPeriodic()
1294         {
1295             return false;
1296         }
1297 
1298         /** {@inheritDoc} */
1299         @Override
1300         public List<Double> aggregate(final List<Double> cumulative, final int count, final Duration aggregation)
1301         {
1302             return cumulative;
1303         }
1304 
1305         /** {@inheritDoc} */
1306         @Override
1307         public String getName()
1308         {
1309             return "vDes0";
1310         }
1311 
1312         /** {@inheritDoc} */
1313         @Override
1314         public String stringValue(final List<Double> aggregate, final String format)
1315         {
1316             return Detector.printListDouble(aggregate, format);
1317         }
1318     }
1319 
1320 }