package org.opentrafficsim.demo; import java.awt.Dimension; import java.io.Serializable; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import javax.naming.NamingException; import org.djunits.unit.util.UNITS; import org.djunits.value.vdouble.scalar.Acceleration; import org.djunits.value.vdouble.scalar.Direction; import org.djunits.value.vdouble.scalar.Duration; import org.djunits.value.vdouble.scalar.Length; import org.djunits.value.vdouble.scalar.Speed; import org.djunits.value.vdouble.scalar.Time; import org.opentrafficsim.base.parameters.ParameterException; import org.opentrafficsim.base.parameters.Parameters; import org.opentrafficsim.core.compatibility.Compatible; import org.opentrafficsim.core.dsol.AbstractOTSModel; import org.opentrafficsim.core.dsol.OTSAnimator; import org.opentrafficsim.core.dsol.OTSSimulatorInterface; import org.opentrafficsim.core.geometry.OTSGeometryException; import org.opentrafficsim.core.geometry.OTSLine3D; import org.opentrafficsim.core.geometry.OTSPoint3D; import org.opentrafficsim.core.gtu.GTUDirectionality; import org.opentrafficsim.core.gtu.GTUException; import org.opentrafficsim.core.gtu.GTUType; import org.opentrafficsim.core.network.NetworkException; import org.opentrafficsim.demo.SequentialLanes.SequentialModel; import org.opentrafficsim.draw.core.OTSDrawingException; import org.opentrafficsim.draw.graphs.ContourDataSource; import org.opentrafficsim.draw.graphs.ContourPlotAcceleration; import org.opentrafficsim.draw.graphs.ContourPlotDensity; import org.opentrafficsim.draw.graphs.ContourPlotFlow; import org.opentrafficsim.draw.graphs.ContourPlotSpeed; import org.opentrafficsim.draw.graphs.GraphPath; import org.opentrafficsim.draw.graphs.TrajectoryPlot; import org.opentrafficsim.draw.graphs.road.GraphLaneUtil; import org.opentrafficsim.kpi.sampling.KpiLaneDirection; import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU; import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory; import org.opentrafficsim.road.gtu.lane.tactical.lmrs.DefaultLMRSPerceptionFactory; import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory; import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner; import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlannerFactory; import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlannerFactory; import org.opentrafficsim.road.network.OTSRoadNetwork; import org.opentrafficsim.road.network.factory.LaneFactory; import org.opentrafficsim.road.network.lane.CrossSectionLink; import org.opentrafficsim.road.network.lane.DirectedLanePosition; import org.opentrafficsim.road.network.lane.Lane; import org.opentrafficsim.road.network.lane.LaneDirection; import org.opentrafficsim.road.network.lane.LaneType; import org.opentrafficsim.road.network.lane.OTSRoadNode; import org.opentrafficsim.road.network.lane.object.sensor.SinkSensor; import org.opentrafficsim.road.network.sampling.RoadSampler; import org.opentrafficsim.swing.graphs.SwingContourPlot; import org.opentrafficsim.swing.graphs.SwingPlot; import org.opentrafficsim.swing.graphs.SwingTrajectoryPlot; import org.opentrafficsim.swing.gui.OTSAnimationPanel; import org.opentrafficsim.swing.gui.OTSSimulationApplication; import nl.tudelft.simulation.dsol.SimRuntimeException; import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterException; import nl.tudelft.simulation.dsol.swing.gui.TablePanel; import nl.tudelft.simulation.dsol.swing.gui.inputparameters.TabbedParameterDialog; import nl.tudelft.simulation.jstats.streams.MersenneTwister; import nl.tudelft.simulation.jstats.streams.StreamInterface; import nl.tudelft.simulation.language.DSOLException; /** * Single lane road consisting of three consecutive links.
* Tests that GTUs correctly transfer themselves onto the next lane and that the graph samplers handle this situation. *

* Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License. *

* $LastChangedDate$, @version $Revision$, by $Author$, * initial version 30 jan. 2015
* @author Alexander Verbraeck * @author Peter Knoppers */ public class SequentialLanes extends OTSSimulationApplication implements UNITS { /** */ private static final long serialVersionUID = 1L; /** * Create a Straight Swing application. * @param title String; the title of the Frame * @param panel OTSAnimationPanel; the tabbed panel to display * @param model SequentialModel; the model * @throws OTSDrawingException on animation error */ public SequentialLanes(final String title, final OTSAnimationPanel panel, final SequentialModel model) throws OTSDrawingException { super(model, panel); OTSRoadNetwork network = model.getNetwork(); System.out.println(network.getLinkMap()); } /** {@inheritDoc} */ @Override protected void addTabs() { addStatisticsTabs(getModel().getSimulator()); } /** * Main program. * @param args String[]; the command line arguments (not used) */ public static void main(final String[] args) { demo(true); } /** * Start the demo. * @param exitOnClose boolean; when running stand-alone: true; when running as part of a demo: false */ public static void demo(final boolean exitOnClose) { try { OTSAnimator simulator = new OTSAnimator("SequentialLanes"); final SequentialModel otsModel = new SequentialModel(simulator); if (TabbedParameterDialog.process(otsModel.getInputParameterMap())) { simulator.initialize(Time.ZERO, Duration.ZERO, Duration.instantiateSI(3600.0), otsModel); OTSAnimationPanel animationPanel = new OTSAnimationPanel(otsModel.getNetwork().getExtent(), new Dimension(800, 600), simulator, otsModel, DEFAULT_COLORER, otsModel.getNetwork()); SequentialLanes app = new SequentialLanes("SequentialLanes", animationPanel, otsModel); app.setExitOnClose(exitOnClose); } else { if (exitOnClose) { System.exit(0); } } } catch (SimRuntimeException | NamingException | RemoteException | OTSDrawingException | DSOLException exception) { exception.printStackTrace(); } } /** * Add the statistics tabs. * @param simulator OTSSimulatorInterface; the simulator on which sampling can be scheduled */ protected final void addStatisticsTabs(final OTSSimulatorInterface simulator) { GraphPath path; try { path = GraphLaneUtil.createPath("Lane", new LaneDirection(getModel().getPath().get(0), GTUDirectionality.DIR_PLUS)); } catch (NetworkException exception) { throw new RuntimeException("Could not create a path as a lane has no set speed limit.", exception); } RoadSampler sampler = new RoadSampler(getModel().getNetwork()); GraphPath.initRecording(sampler, path); ContourDataSource dataPool = new ContourDataSource<>(sampler.getSamplerData(), path); TablePanel charts = new TablePanel(3, 2); SwingPlot plot = null; plot = new SwingTrajectoryPlot(new TrajectoryPlot("TrajectoryPlot", Duration.instantiateSI(10.0), simulator, sampler .getSamplerData(), path)); charts.setCell(plot.getContentPane(), 0, 0); plot = new SwingContourPlot(new ContourPlotDensity("DensityPlot", simulator, dataPool)); charts.setCell(plot.getContentPane(), 1, 0); plot = new SwingContourPlot(new ContourPlotSpeed("SpeedPlot", simulator, dataPool)); charts.setCell(plot.getContentPane(), 2, 0); plot = new SwingContourPlot(new ContourPlotFlow("FlowPlot", simulator, dataPool)); charts.setCell(plot.getContentPane(), 1, 1); plot = new SwingContourPlot(new ContourPlotAcceleration("AccelerationPlot", simulator, dataPool)); charts.setCell(plot.getContentPane(), 2, 1); getAnimationPanel().getTabbedPane().addTab(getAnimationPanel().getTabbedPane().getTabCount(), "statistics ", charts); } /** * Build the sequential model. *

* Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. *
* BSD-style license. See OpenTrafficSim License. *

* $LastChangedDate$, @version $Revision$, by $Author$, * initial version 0 jan. 2015
* @author Peter Knoppers */ static class SequentialModel extends AbstractOTSModel implements UNITS { /** */ private static final long serialVersionUID = 20150130L; /** The network. */ private final OTSRoadNetwork network = new OTSRoadNetwork("network", true, getSimulator()); /** The nodes of our network in the order that all GTUs will visit them. */ private List nodes = new ArrayList<>(); /** Strategical planner generator for cars. */ private LaneBasedStrategicalPlannerFactory strategicalPlannerGeneratorCars = null; /** Strategical planner generator for trucks. */ private LaneBasedStrategicalPlannerFactory strategicalPlannerGeneratorTrucks = null; /** Car parameters. */ private Parameters parametersCar; /** Truck parameters. */ private Parameters parametersTruck; /** The probability that the next generated GTU is a passenger car. */ private double carProbability; /** The headway (inter-vehicle time). */ private Duration headway; /** Number of cars created. */ private int carsCreated = 0; /** Minimum distance. */ private Length minimumDistance = new Length(0, METER); /** The Lane where newly created Cars initially placed on. */ private Lane initialLane; /** Maximum distance. */ private Length maximumDistance = new Length(2001, METER); /** The random number generator used to decide what kind of GTU to generate. */ private StreamInterface stream = new MersenneTwister(12345); /** The sequence of Lanes that all vehicles will follow. */ private List path = new ArrayList<>(); /** The speedLimit on all Lanes. */ private Speed speedLimit; /** * @param simulator OTSSimulatorInterface; the simulator for this model */ SequentialModel(final OTSSimulatorInterface simulator) { super(simulator); InputParameterHelper.makeInputParameterMapCarTruck(this.inputParameterMap, 1.0); } /** * @return a newly created path (which all GTUs in this simulation will follow). */ public List getPath() { return new ArrayList<>(this.path); } /** {@inheritDoc} */ @Override public final void constructModel() throws SimRuntimeException { this.speedLimit = new Speed(100, KM_PER_HOUR); // TODO Bezier curves make 180 degree mistake when minus is true boolean minus = false; this.nodes = new ArrayList<>(); try { OTSPoint3D p2 = new OTSPoint3D(1020, 3); OTSPoint3D p3 = new OTSPoint3D(2000, 197); Direction dir23 = p2.horizontalDirection(p3); OTSRoadNode n0 = new OTSRoadNode(this.network, "Node-0-(0,0)", new OTSPoint3D(0, 0), Direction.ZERO); OTSRoadNode n1 = new OTSRoadNode(this.network, "Node-1-(1000,0)", new OTSPoint3D(1000, 0), Direction.ZERO); OTSRoadNode n2 = new OTSRoadNode(this.network, "Node-2-(1020,3)", p2, dir23); OTSRoadNode n3 = new OTSRoadNode(this.network, "Node-3-(2000,197)", p3, dir23); OTSRoadNode n4 = new OTSRoadNode(this.network, "Node-4-(2020,200)", new OTSPoint3D(2020, 200), Direction.ZERO); OTSRoadNode n5 = new OTSRoadNode(this.network, "Node-5-(2200,200)", new OTSPoint3D(2200, 200), Direction.ZERO); this.nodes.addAll(Arrays.asList(new OTSRoadNode[] {n0, n1, n2, n3, n4, n5})); LaneType laneType = this.network.getLaneType(LaneType.DEFAULTS.TWO_WAY_LANE); // Now we can build a series of Links with one Lane on them ArrayList links = new ArrayList<>(); OTSLine3D l01 = new OTSLine3D(n0.getPoint(), n1.getPoint()); OTSLine3D l12 = LaneFactory.makeBezier(n0, n1, n2, n3); OTSLine3D l23 = minus ? new OTSLine3D(n3.getPoint(), n2.getPoint()) : new OTSLine3D(n2.getPoint(), n3 .getPoint()); OTSLine3D l34 = LaneFactory.makeBezier(n2, n3, n4, n5); OTSLine3D l45 = new OTSLine3D(n4.getPoint(), n5.getPoint()); OTSLine3D[] lines = new OTSLine3D[] {l01, l12, l23, l34, l45}; for (int i = 1; i < this.nodes.size(); i++) { OTSRoadNode fromNode = this.nodes.get(i - 1); OTSRoadNode toNode = this.nodes.get(i); OTSLine3D line = lines[i - 1]; String linkName = fromNode.getId() + "-" + toNode.getId(); // LongitudinalDirectionality direction = line.equals(l23) && minus ? LongitudinalDirectionality.DIR_MINUS // : LongitudinalDirectionality.DIR_PLUS; Lane[] lanes = LaneFactory.makeMultiLane(this.network, linkName, fromNode, toNode, line.getPoints(), 1, laneType, this.speedLimit, this.simulator); if (i == this.nodes.size() - 1) { new SinkSensor(lanes[0], new Length(100.0, METER), Compatible.EVERYTHING, this.simulator); } this.path.add(lanes[0]); links.add(lanes[0].getParentLink()); if (1 == i) { this.initialLane = lanes[0]; } } this.carProbability = (double) getInputParameter("generic.carProbability"); this.parametersCar = InputParameterHelper.getParametersCar(getInputParameterMap()); this.parametersTruck = InputParameterHelper.getParametersTruck(getInputParameterMap()); this.strategicalPlannerGeneratorCars = new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactory( new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory())); this.strategicalPlannerGeneratorTrucks = new LaneBasedStrategicalRoutePlannerFactory(new LMRSFactory( new IDMPlusFactory(this.stream), new DefaultLMRSPerceptionFactory())); // 1500 [veh / hour] == 2.4s headway this.headway = new Duration(3600.0 / 1500.0, SECOND); // Schedule creation of the first car (it will re-schedule itself one headway later, etc.). this.simulator.scheduleEventAbs(Time.ZERO, this, this, "generateCar", null); } catch (NamingException | NetworkException | OTSGeometryException | ParameterException | InputParameterException | GTUException exception) { exception.printStackTrace(); } } /** {@inheritDoc} */ @Override public OTSRoadNetwork getNetwork() { return this.network; } /** * @return minimumDistance */ public final Length getMinimumDistance() { return this.minimumDistance; } /** * @return maximumDistance */ public final Length getMaximumDistance() { return this.maximumDistance; } /** * Generate cars at a fixed rate (implemented by re-scheduling this method). */ protected final void generateCar() { try { boolean generateTruck = this.stream.nextDouble() > this.carProbability; Length vehicleLength = new Length(generateTruck ? 15 : 4, METER); LaneBasedIndividualGTU gtu = new LaneBasedIndividualGTU("" + (++this.carsCreated), this.network.getGtuType( GTUType.DEFAULTS.CAR), vehicleLength, new Length(1.8, METER), new Speed(200, KM_PER_HOUR), vehicleLength .times(0.5), this.simulator, this.network); gtu.setParameters(generateTruck ? this.parametersTruck : this.parametersCar); gtu.setNoLaneChangeDistance(Length.ZERO); gtu.setMaximumAcceleration(Acceleration.instantiateSI(3.0)); gtu.setMaximumDeceleration(Acceleration.instantiateSI(-8.0)); // strategical planner LaneBasedStrategicalPlanner strategicalPlanner = generateTruck ? this.strategicalPlannerGeneratorTrucks.create( gtu, null, null, null) : this.strategicalPlannerGeneratorCars.create(gtu, null, null, null); Set initialPositions = new LinkedHashSet<>(1); Length initialPosition = new Length(20, METER); initialPositions.add(new DirectedLanePosition(this.initialLane, initialPosition, GTUDirectionality.DIR_PLUS)); Speed initialSpeed = new Speed(100.0, KM_PER_HOUR); gtu.init(strategicalPlanner, initialPositions, initialSpeed); this.simulator.scheduleEventRel(this.headway, this, this, "generateCar", null); } catch (SimRuntimeException | NetworkException | GTUException | OTSGeometryException exception) { exception.printStackTrace(); } } /** {@inheritDoc} */ @Override public Serializable getSourceId() { return "SequentialModel"; } } }