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.OTSNode;
29  import org.opentrafficsim.core.units.distributions.ContinuousDistMass;
30  import org.opentrafficsim.road.gtu.generator.od.DefaultGTUCharacteristicsGeneratorOD;
31  import org.opentrafficsim.road.gtu.generator.od.ODApplier;
32  import org.opentrafficsim.road.gtu.generator.od.ODOptions;
33  import org.opentrafficsim.road.gtu.generator.od.StrategicalPlannerFactorySupplierOD;
34  import org.opentrafficsim.road.gtu.generator.od.StrategicalPlannerFactorySupplierOD.TacticalPlannerFactorySupplierOD;
35  import org.opentrafficsim.road.gtu.lane.LaneBasedGTU;
36  import org.opentrafficsim.road.gtu.lane.VehicleModel;
37  import org.opentrafficsim.road.gtu.lane.VehicleModelFactory;
38  import org.opentrafficsim.road.gtu.lane.tactical.AbstractLaneBasedTacticalPlannerFactory;
39  import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedTacticalPlannerFactory;
40  import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory;
41  import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory;
42  import org.opentrafficsim.road.gtu.lane.tactical.steering.SteeringLmrs;
43  import org.opentrafficsim.road.gtu.lane.tactical.util.Steering;
44  import org.opentrafficsim.road.gtu.lane.tactical.util.Steering.FeedbackTable;
45  import org.opentrafficsim.road.gtu.lane.tactical.util.Steering.FeedbackTable.FeedbackVector;
46  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Cooperation;
47  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.GapAcceptance;
48  import org.opentrafficsim.road.gtu.lane.tactical.util.lmrs.Synchronization;
49  import org.opentrafficsim.road.gtu.strategical.od.Categorization;
50  import org.opentrafficsim.road.gtu.strategical.od.Category;
51  import org.opentrafficsim.road.gtu.strategical.od.Interpolation;
52  import org.opentrafficsim.road.gtu.strategical.od.ODMatrix;
53  import org.opentrafficsim.road.network.OTSRoadNetwork;
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          try
100         {
101             new SteeringSimulation(args).start();
102         }
103         catch (Exception ex)
104         {
105             ex.printStackTrace();
106         }
107     }
108 
109     /**
110      * @param properties String[]; properties
111      */
112     protected SteeringSimulation(final String[] properties)
113     {
114         super("Steering simulation", "Steering simulation", properties);
115     }
116 
117     /**
118      * Sets up the simulation based on provided properties. Properties can be obtained with {@code getProperty()}. Setting up a
119      * simulation should at least create a network and some demand. Additionally this may setup traffic control, sampling, etc.
120      * @param sim OTSSimulatorInterface; simulator
121      * @return OTSRoadNetwork; network
122      * @throws Exception on any exception
123      */
124     protected OTSRoadNetwork setupSimulation(final OTSSimulatorInterface sim) throws Exception
125     {
126         OTSRoadNetwork network = new OTSRoadNetwork("Steering network", true);
127         Length laneWidth = Length.createSI(3.5);
128         Length stripeWidth = Length.createSI(0.2);
129 
130         // points
131         OTSPoint3D pointA = new OTSPoint3D(0, 0);
132         OTSPoint3D pointB = new OTSPoint3D(2000, 0);
133         OTSPoint3D pointC = new OTSPoint3D(2250, 0);
134         OTSPoint3D pointD = new OTSPoint3D(3250, 0);
135         OTSPoint3D pointE = new OTSPoint3D(1500, -30);
136 
137         // nodes
138         OTSNode nodeA = new OTSNode(network, "A", pointA);
139         OTSNode nodeB = new OTSNode(network, "B", pointB);
140         OTSNode nodeC = new OTSNode(network, "C", pointC);
141         OTSNode nodeD = new OTSNode(network, "D", pointD);
142         OTSNode nodeE = new OTSNode(network, "E", pointE);
143 
144         // links
145         CrossSectionLink linkAB =
146                 new CrossSectionLink(network, "AB", nodeA, nodeB, network.getLinkType(LinkType.DEFAULTS.FREEWAY),
147                         new OTSLine3D(pointA, pointB), sim, LaneKeepingPolicy.KEEPRIGHT);
148         CrossSectionLink linkBC =
149                 new CrossSectionLink(network, "BC", nodeB, nodeC, network.getLinkType(LinkType.DEFAULTS.FREEWAY),
150                         new OTSLine3D(pointB, pointC), sim, LaneKeepingPolicy.KEEPRIGHT);
151         CrossSectionLink linkCD =
152                 new CrossSectionLink(network, "CD", nodeC, nodeD, network.getLinkType(LinkType.DEFAULTS.FREEWAY),
153                         new OTSLine3D(pointC, pointD), sim, LaneKeepingPolicy.KEEPRIGHT);
154         CrossSectionLink linkEB =
155                 new CrossSectionLink(network, "EB", nodeE, nodeB, network.getLinkType(LinkType.DEFAULTS.FREEWAY),
156                         Bezier.cubic(nodeE.getLocation(), nodeB.getLocation()), sim, LaneKeepingPolicy.KEEPRIGHT);
157 
158         // lanes and stripes
159         int n = getIntegerProperty("numberOfLanes");
160         List<Lane> originLanes = new ArrayList<>();
161         for (int i = 0; i < n; i++)
162         {
163             for (CrossSectionLink link : new CrossSectionLink[] {linkAB, linkBC, linkCD})
164             {
165                 Lane lane = new Lane(link, "Lane " + (i + 1), laneWidth.multiplyBy((0.5 + i)), laneWidth,
166                         network.getLaneType(LaneType.DEFAULTS.FREEWAY), new Speed(120, SpeedUnit.KM_PER_HOUR));
167                 Length offset = laneWidth.multiplyBy(i + 1.0);
168                 Stripe stripe = new Stripe(link, offset, offset, stripeWidth);
169                 if (i < n - 1)
170                 {
171                     stripe.addPermeability(network.getGtuType(GTUType.DEFAULTS.VEHICLE), Permeable.BOTH);
172                 }
173                 // sink sensors
174                 if (lane.getParentLink().getId().equals("CD"))
175                 {
176                     new SinkSensor(lane, lane.getLength().minus(Length.createSI(100.0)), sim);
177                     // detectors 100m after on ramp
178                     new Detector(lane.getFullId(), lane, Length.createSI(100.0), sim); // id equal to lane, may be different
179                 }
180                 if (lane.getParentLink().getId().equals("AB"))
181                 {
182                     originLanes.add(lane);
183                 }
184             }
185         }
186         new Stripe(linkAB, Length.ZERO, Length.ZERO, stripeWidth);
187         Stripe stripe = new Stripe(linkBC, Length.ZERO, Length.ZERO, stripeWidth);
188         stripe.addPermeability(network.getGtuType(GTUType.DEFAULTS.VEHICLE), Permeable.LEFT);
189         new Stripe(linkCD, Length.ZERO, Length.ZERO, stripeWidth);
190         new Lane(linkBC, "Acceleration lane", laneWidth.multiplyBy(-0.5), laneWidth,
191                 network.getLaneType(LaneType.DEFAULTS.FREEWAY), new Speed(120, SpeedUnit.KM_PER_HOUR));
192         new Lane(linkEB, "Onramp", laneWidth.multiplyBy(-0.5), laneWidth, network.getLaneType(LaneType.DEFAULTS.FREEWAY),
193                 new Speed(120, SpeedUnit.KM_PER_HOUR));
194         new Stripe(linkEB, Length.ZERO, Length.ZERO, stripeWidth);
195         new Stripe(linkEB, laneWidth.neg(), laneWidth.neg(), stripeWidth);
196         new Stripe(linkBC, laneWidth.neg(), laneWidth.neg(), stripeWidth);
197 
198         // OD
199         List<OTSNode> origins = new ArrayList<>();
200         origins.add(nodeA);
201         origins.add(nodeE);
202         List<OTSNode> destinations = new ArrayList<>();
203         destinations.add(nodeD);
204         TimeVector timeVector = new TimeVector(new double[] {0.0, 0.5, 1.0}, TimeUnit.BASE_HOUR, StorageType.DENSE);
205         Interpolation interpolation = Interpolation.LINEAR; // or STEPWISE
206         Categorization categorization = new Categorization("GTU type", GTUType.class);
207         Category carCategory = new Category(categorization, network.getGtuType(GTUType.DEFAULTS.CAR));
208         Category truCategory = new Category(categorization, network.getGtuType(GTUType.DEFAULTS.TRUCK));
209         ODMatrix odMatrix = new ODMatrix("Steering OD", origins, destinations, categorization, timeVector, interpolation);
210 
211         odMatrix.putDemandVector(nodeA, nodeD, carCategory, freq(new double[] {1000.0, 2000.0, 0.0}));
212         odMatrix.putDemandVector(nodeA, nodeD, truCategory, freq(new double[] {100.0, 200.0, 0.0}));
213         odMatrix.putDemandVector(nodeE, nodeD, carCategory, freq(new double[] {500.0, 1000.0, 0.0}));
214 
215         // anonymous tactical-planner-factory supplier
216         AbstractLaneBasedTacticalPlannerFactory<SteeringLmrs> car = new AbstractLaneBasedTacticalPlannerFactory<SteeringLmrs>(
217                 new IDMPlusFactory(sim.getReplication().getStream("generation")), new DefaultLMRSPerceptionFactory())
218         {
219             @Override
220             public SteeringLmrs create(final LaneBasedGTU gtu) throws GTUException
221             {
222                 return new SteeringLmrs(nextCarFollowingModel(gtu), gtu, getPerceptionFactory().generatePerception(gtu),
223                         Synchronization.PASSIVE, Cooperation.PASSIVE, GapAcceptance.INFORMED, FEEDBACK_CAR);
224             }
225 
226             @Override
227             public Parameters getParameters() throws ParameterException
228             {
229                 // TODO: add parameters if required (run and wait for ParameterException to find missing parameters)
230                 ParameterSet parameters = new ParameterSet();
231                 getCarFollowingParameters().setAllIn(parameters);
232                 parameters.setDefaultParameters(Steering.class);
233                 return parameters;
234             }
235         };
236         TacticalPlannerFactorySupplierOD tacticalPlannerFactorySupplierOD = new TacticalPlannerFactorySupplierOD()
237         {
238             @Override
239             public LaneBasedTacticalPlannerFactory<SteeringLmrs> getFactory(final Node origin, final Node destination,
240                     final Category category, final StreamInterface randomStream)
241             {
242                 GTUType gtuType = category.get(GTUType.class);
243                 if (gtuType.equals(network.getGtuType(GTUType.DEFAULTS.CAR)))
244                 {
245                     return car;
246                 }
247                 else
248                 {
249                     // TODO: other GTU types
250                     return null;
251                 }
252             };
253         };
254         // anonymous vehicle model factory
255         // TODO: supply mass and inertia values, possibly randomized, correlated?
256         ContinuousDistMass massDistCar =
257                 new ContinuousDistMass(new DistUniform(sim.getReplication().getStream("generation"), 600, 1200), MassUnit.SI);
258         ContinuousDistMass massDistTruck =
259                 new ContinuousDistMass(new DistUniform(sim.getReplication().getStream("generation"), 2000, 10000), MassUnit.SI);
260         double momentOfInertiaAboutZ = 100; // no idea...
261         VehicleModelFactory vehicleModelGenerator = new VehicleModelFactory()
262         {
263             @Override
264             public VehicleModel create(final GTUType gtuType)
265             {
266                 Mass mass =
267                         gtuType.isOfType(network.getGtuType(GTUType.DEFAULTS.CAR)) ? massDistCar.draw() : massDistTruck.draw();
268                 return new VehicleModel.MassBased(mass, momentOfInertiaAboutZ);
269             }
270         };
271         // characteristics generator using OD info and default route based strategical level
272         DefaultGTUCharacteristicsGeneratorOD characteristicsGenerator = new DefaultGTUCharacteristicsGeneratorOD.Factory()
273                 .setFactorySupplier(StrategicalPlannerFactorySupplierOD.route(tacticalPlannerFactorySupplierOD))
274                 .setVehicleModelGenerator(vehicleModelGenerator).create();
275 
276         // od options
277         ODOptions odOptions = new ODOptions().set(ODOptions.NO_LC_DIST, Length.createSI(300.0)).set(ODOptions.GTU_TYPE,
278                 characteristicsGenerator);
279         ODApplier.applyOD(network, odMatrix, sim, odOptions);
280 
281         return network;
282     }
283 
284     /**
285      * Creates a frequency vector.
286      * @param array double[]; array in veh/h
287      * @return FrequencyVector; frequency vector
288      * @throws ValueException on problem
289      */
290     private FrequencyVector freq(final double[] array) throws ValueException
291     {
292         return new FrequencyVector(array, FrequencyUnit.PER_HOUR, StorageType.DENSE);
293     }
294 
295 }