View Javadoc
1   package org.opentrafficsim.demo.steering;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   
6   import org.djunits.unit.FrequencyUnit;
7   import org.djunits.unit.MassUnit;
8   import org.djunits.unit.SpeedUnit;
9   import org.djunits.unit.TimeUnit;
10  import org.djunits.value.StorageType;
11  import org.djunits.value.ValueException;
12  import org.djunits.value.vdouble.scalar.Length;
13  import org.djunits.value.vdouble.scalar.Mass;
14  import org.djunits.value.vdouble.scalar.Speed;
15  import org.djunits.value.vdouble.vector.FrequencyVector;
16  import org.djunits.value.vdouble.vector.TimeVector;
17  import org.opentrafficsim.base.parameters.ParameterException;
18  import org.opentrafficsim.base.parameters.ParameterSet;
19  import org.opentrafficsim.base.parameters.Parameters;
20  import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
21  import org.opentrafficsim.core.geometry.Bezier;
22  import org.opentrafficsim.core.geometry.OTSLine3D;
23  import org.opentrafficsim.core.geometry.OTSPoint3D;
24  import org.opentrafficsim.core.gtu.GTUException;
25  import org.opentrafficsim.core.gtu.GTUType;
26  import org.opentrafficsim.core.network.LinkType;
27  import org.opentrafficsim.core.network.Node;
28  import org.opentrafficsim.core.network.OTSNetwork;
29  import org.opentrafficsim.core.network.OTSNode;
30  import org.opentrafficsim.core.units.distributions.ContinuousDistMass;
31  import org.opentrafficsim.road.gtu.generator.od.DefaultGTUCharacteristicsGeneratorOD;
32  import org.opentrafficsim.road.gtu.generator.od.ODApplier;
33  import org.opentrafficsim.road.gtu.generator.od.ODOptions;
34  import org.opentrafficsim.road.gtu.generator.od.StrategicalPlannerFactorySupplierOD;
35  import org.opentrafficsim.road.gtu.generator.od.StrategicalPlannerFactorySupplierOD.TacticalPlannerFactorySupplierOD;
36  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
37  import org.opentrafficsim.road.gtu.lane.VehicleModel;
38  import org.opentrafficsim.road.gtu.lane.VehicleModelFactory;
39  import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlannerFactory;
40  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
41  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
42  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
43  import org.opentrafficsim.road.gtu.lane.tactical.steering.SteeringLmrs;
44  import org.opentrafficsim.road.gtu.lane.tactical.util.Steering;
45  import org.opentrafficsim.road.gtu.lane.tactical.util.Steering.FeedbackTable;
46  import org.opentrafficsim.road.gtu.lane.tactical.util.Steering.FeedbackTable.FeedbackVector;
47  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
48  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
49  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
50  import org.opentrafficsim.road.gtu.strategical.od.Categorization;
51  import org.opentrafficsim.road.gtu.strategical.od.Category;
52  import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
53  import org.opentrafficsim.road.gtu.strategical.od.ODMatrix;
54  import org.opentrafficsim.road.network.lane.CrossSectionLink;
55  import org.opentrafficsim.road.network.lane.Lane;
56  import org.opentrafficsim.road.network.lane.LaneType;
57  import org.opentrafficsim.road.network.lane.Stripe;
58  import org.opentrafficsim.road.network.lane.Stripe.Permeable;
59  import org.opentrafficsim.road.network.lane.changing.LaneKeepingPolicy;
60  import org.opentrafficsim.road.network.lane.object.sensor.Detector;
61  import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor;
62  import org.opentrafficsim.swing.script.AbstractSimulationScript;
63  
64  import nl.tudelft.simulation.jstats.distributions.DistUniform;
65  import nl.tudelft.simulation.jstats.streams.StreamInterface;
66  
67  /**
68   * Simulation script for steering functionality.
69   * <p>
70   * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
71   * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
72   * <p>
73   * @version $Revision$, $LastChangedDate$, by $Author$, initial version 8 jan. 2019 <br>
74   * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
75   * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
76   * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
77   */
78  public class SteeringSimulation extends AbstractSimulationScript
79  {
80  
81      /** Feedback table. */
82      static final FeedbackTable FEEDBACK_CAR;
83  
84      static
85      {
86          // TODO: define tables
87          List<FeedbackVector> list = new ArrayList<>();
88          list.add(new FeedbackVector(new Speed(25.0, SpeedUnit.KM_PER_HOUR), 0.0, 0.0, 0.0, 0.0));
89          list.add(new FeedbackVector(new Speed(75.0, SpeedUnit.KM_PER_HOUR), 0.0, 0.0, 0.0, 0.0));
90          FEEDBACK_CAR = new FeedbackTable(list);
91      }
92  
93      /**
94       * Start a simulation.
95       * @param args String...; command line arguments
96       */
97      public static void main(final String... args)
98      {
99          new SteeringSimulation(args).start();
100     }
101 
102     /**
103      * @param properties String[]; properties
104      */
105     protected SteeringSimulation(final String[] properties)
106     {
107         super("Steering simulation", "Steering simulation", properties);
108     }
109 
110     /**
111      * Sets up the simulation based on provided properties. Properties can be obtained with {@code getProperty()}. Setting up a
112      * simulation should at least create a network and some demand. Additionally this may setup traffic control, sampling, etc.
113      * @param sim OTSSimulatorInterface; simulator
114      * @return OTSNetwork; network
115      * @throws Exception on any exception
116      */
117     protected OTSNetwork setupSimulation(final OTSSimulatorInterface sim) throws Exception
118     {
119         OTSNetwork network = new OTSNetwork("Steering network");
120         Length laneWidth = Length.createSI(3.5);
121         Length stripeWidth = Length.createSI(0.2);
122 
123         // points
124         OTSPoint3D pointA = new OTSPoint3D(0, 0);
125         OTSPoint3D pointB = new OTSPoint3D(2000, 0);
126         OTSPoint3D pointC = new OTSPoint3D(2250, 0);
127         OTSPoint3D pointD = new OTSPoint3D(3250, 0);
128         OTSPoint3D pointE = new OTSPoint3D(1500, -30);
129 
130         // nodes
131         OTSNode nodeA = new OTSNode(network, "A", pointA);
132         OTSNode nodeB = new OTSNode(network, "B", pointB);
133         OTSNode nodeC = new OTSNode(network, "C", pointC);
134         OTSNode nodeD = new OTSNode(network, "D", pointD);
135         OTSNode nodeE = new OTSNode(network, "E", pointE);
136 
137         // links
138         CrossSectionLink linkAB = new CrossSectionLink(network, "AB", nodeA, nodeB, LinkType.FREEWAY,
139                 new OTSLine3D(pointA, pointB), sim, LaneKeepingPolicy.KEEP_RIGHT);
140         CrossSectionLink linkBC = new CrossSectionLink(network, "BC", nodeB, nodeC, LinkType.FREEWAY,
141                 new OTSLine3D(pointB, pointC), sim, LaneKeepingPolicy.KEEP_RIGHT);
142         CrossSectionLink linkCD = new CrossSectionLink(network, "CD", nodeC, nodeD, LinkType.FREEWAY,
143                 new OTSLine3D(pointC, pointD), sim, LaneKeepingPolicy.KEEP_RIGHT);
144         CrossSectionLink linkEB = new CrossSectionLink(network, "EB", nodeE, nodeB, LinkType.FREEWAY,
145                 Bezier.cubic(nodeE.getLocation(), nodeB.getLocation()), sim, LaneKeepingPolicy.KEEP_RIGHT);
146 
147         // lanes and stripes
148         int n = getIntegerProperty("numberOfLanes");
149         List<Lane> originLanes = new ArrayList<>();
150         for (int i = 0; i < n; i++)
151         {
152             for (CrossSectionLink link : new CrossSectionLink[] { linkAB, linkBC, linkCD })
153             {
154                 Lane lane = new Lane(link, "Lane " + (i + 1), laneWidth.multiplyBy((0.5 + i)), laneWidth, LaneType.FREEWAY,
155                         new Speed(120, SpeedUnit.KM_PER_HOUR), null);
156                 Length offset = laneWidth.multiplyBy(i + 1.0);
157                 Stripe stripe = new Stripe(link, offset, offset, stripeWidth);
158                 if (i < n - 1)
159                 {
160                     stripe.addPermeability(GTUType.VEHICLE, Permeable.BOTH);
161                 }
162                 // sink sensors
163                 if (lane.getParentLink().getId().equals("CD"))
164                 {
165                     new SinkSensor(lane, lane.getLength().minus(Length.createSI(100.0)), sim);
166                     // detectors 100m after on ramp
167                     new Detector(lane.getFullId(), lane, Length.createSI(100.0), sim); // id equal to lane, may be different
168                 }
169                 if (lane.getParentLink().getId().equals("AB"))
170                 {
171                     originLanes.add(lane);
172                 }
173             }
174         }
175         new Stripe(linkAB, Length.ZERO, Length.ZERO, stripeWidth);
176         Stripe stripe = new Stripe(linkBC, Length.ZERO, Length.ZERO, stripeWidth);
177         stripe.addPermeability(GTUType.VEHICLE, Permeable.LEFT);
178         new Stripe(linkCD, Length.ZERO, Length.ZERO, stripeWidth);
179         new Lane(linkBC, "Acceleration lane", laneWidth.multiplyBy(-0.5), laneWidth, LaneType.FREEWAY,
180                 new Speed(120, SpeedUnit.KM_PER_HOUR), null);
181         new Lane(linkEB, "Onramp", laneWidth.multiplyBy(-0.5), laneWidth, LaneType.FREEWAY,
182                 new Speed(120, SpeedUnit.KM_PER_HOUR), null);
183         new Stripe(linkEB, Length.ZERO, Length.ZERO, stripeWidth);
184         new Stripe(linkEB, laneWidth.neg(), laneWidth.neg(), stripeWidth);
185         new Stripe(linkBC, laneWidth.neg(), laneWidth.neg(), stripeWidth);
186 
187         // OD
188         List<OTSNode> origins = new ArrayList<>();
189         origins.add(nodeA);
190         origins.add(nodeE);
191         List<OTSNode> destinations = new ArrayList<>();
192         destinations.add(nodeD);
193         TimeVector timeVector = new TimeVector(new double[] { 0.0, 0.5, 1.0 }, TimeUnit.BASE_HOUR, StorageType.DENSE);
194         Interpolation interpolation = Interpolation.LINEAR; // or STEPWISE
195         Categorization categorization = new Categorization("GTU type", GTUType.class);
196         Category carCategory = new Category(categorization, GTUType.CAR);
197         Category truCategory = new Category(categorization, GTUType.TRUCK);
198         ODMatrix odMatrix = new ODMatrix("Steering OD", origins, destinations, categorization, timeVector, interpolation);
199 
200         odMatrix.putDemandVector(nodeA, nodeD, carCategory, freq(new double[] { 1000.0, 2000.0, 0.0 }));
201         odMatrix.putDemandVector(nodeA, nodeD, truCategory, freq(new double[] { 100.0, 200.0, 0.0 }));
202         odMatrix.putDemandVector(nodeE, nodeD, carCategory, freq(new double[] { 500.0, 1000.0, 0.0 }));
203 
204         // anonymous tactical-planner-factory supplier
205         AbstractLaneBasedTacticalPlannerFactory<SteeringLmrs> car = new AbstractLaneBasedTacticalPlannerFactory<SteeringLmrs>(
206                 new IDMPlusFactory(sim.getReplication().getStream("generation")), new DefaultLMRSPerceptionFactory())
207         {
208             @Override
209             public SteeringLmrs create(final LaneBasedGTU gtu) throws GTUException
210             {
211                 return new SteeringLmrs(nextCarFollowingModel(gtu), gtu, getPerceptionFactory().generatePerception(gtu),
212                         Synchronization.PASSIVE, Cooperation.PASSIVE, GapAcceptance.INFORMED, FEEDBACK_CAR);
213             }
214 
215             @Override
216             public Parameters getParameters() throws ParameterException
217             {
218                 // TODO: add parameters if required (run and wait for ParameterException to find missing parameters)
219                 ParameterSet parameters = new ParameterSet();
220                 getCarFollowingParameters().setAllIn(parameters);
221                 parameters.setDefaultParameters(Steering.class);
222                 return parameters;
223             }
224         };
225         TacticalPlannerFactorySupplierOD tacticalPlannerFactorySupplierOD = new TacticalPlannerFactorySupplierOD()
226         {
227             @Override
228             public LaneBasedTacticalPlannerFactory<SteeringLmrs> getFactory(final Node origin, final Node destination,
229                     final Category category, final StreamInterface randomStream)
230             {
231                 GTUType gtuType = category.get(GTUType.class);
232                 if (gtuType.equals(GTUType.CAR))
233                 {
234                     return car;
235                 }
236                 else
237                 {
238                     // TODO: other GTU types
239                     return null;
240                 }
241             };
242         };
243         // anonymous vehicle model factory
244         // TODO: supply mass and inertia values, possibly randomized, correlated?
245         ContinuousDistMass massDistCar =
246                 new ContinuousDistMass(new DistUniform(sim.getReplication().getStream("generation"), 600, 1200), MassUnit.SI);
247         ContinuousDistMass massDistTruck =
248                 new ContinuousDistMass(new DistUniform(sim.getReplication().getStream("generation"), 2000, 10000), MassUnit.SI);
249         double momentOfInertiaAboutZ = 100; // no idea...
250         VehicleModelFactory vehicleModelGenerator = new VehicleModelFactory()
251         {
252             @Override
253             public VehicleModel create(final GTUType gtuType)
254             {
255                 Mass mass = gtuType.isOfType(GTUType.CAR) ? massDistCar.draw() : massDistTruck.draw();
256                 return new VehicleModel.MassBased(mass, momentOfInertiaAboutZ);
257             }
258         };
259         // characteristics generator using OD info and default route based strategical level
260         DefaultGTUCharacteristicsGeneratorOD characteristicsGenerator = new DefaultGTUCharacteristicsGeneratorOD.Factory()
261                 .setFactorySupplier(StrategicalPlannerFactorySupplierOD.route(tacticalPlannerFactorySupplierOD))
262                 .setVehicleModelGenerator(vehicleModelGenerator).create();
263 
264         // od options
265         ODOptions odOptions = new ODOptions().set(ODOptions.NO_LC_DIST, Length.createSI(300.0)).set(ODOptions.GTU_TYPE,
266                 characteristicsGenerator);
267         ODApplier.applyOD(network, odMatrix, sim, odOptions);
268 
269         return network;
270     }
271 
272     /**
273      * Creates a frequency vector.
274      * @param array double[]; array in veh/h
275      * @return FrequencyVector; frequency vector
276      * @throws ValueException on problem
277      */
278     private FrequencyVector freq(final double[] array) throws ValueException
279     {
280         return new FrequencyVector(array, FrequencyUnit.PER_HOUR, StorageType.DENSE);
281     }
282 
283 }