* Copyright (c) 2013-2016 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 AbstractWrappableAnimation implements UNITS
{
/** */
private static final long serialVersionUID = 1L;
/** The model. */
private SequentialModel model;
/**
* Create a SequentialLanes simulation.
* @throws PropertyException when the provided properties could not be handled
*/
public SequentialLanes() throws PropertyException
{
List> outputProperties = new ArrayList<>();
outputProperties.add(new BooleanProperty("DensityPlot", "Density", "Density contour plot", true, false, 0));
outputProperties.add(new BooleanProperty("FlowPlot", "Flow", "Flow contour plot", true, false, 1));
outputProperties.add(new BooleanProperty("SpeedPlot", "Speed", "Speed contour plot", true, false, 2));
outputProperties
.add(new BooleanProperty("AccelerationPlot", "Acceleration", "Acceleration contour plot", true, false, 3));
outputProperties.add(
new BooleanProperty("TrajectoryPlot", "Trajectories", "Trajectory (time/distance) diagram", true, false, 4));
this.properties.add(new CompoundProperty("OutputGraphs", "Output graphs", "Select the graphical output",
outputProperties, true, 1000));
}
/** {@inheritDoc} */
@Override
public final void stopTimersThreads()
{
super.stopTimersThreads();
this.model = null;
}
/**
* Main program.
* @param args String[]; the command line arguments (not used)
* @throws SimRuntimeException when simulation cannot be created with given parameters
*/
public static void main(final String[] args) throws SimRuntimeException
{
SwingUtilities.invokeLater(new Runnable()
{
@SuppressWarnings("synthetic-access")
@Override
public void run()
{
try
{
SequentialLanes sequential = new SequentialLanes();
List> localProperties = sequential.getProperties();
try
{
localProperties.add(new ProbabilityDistributionProperty("TrafficComposition", "Traffic composition",
"Mix of passenger cars and trucks", new String[] { "passenger car", "truck" },
new Double[] { 0.8, 0.2 }, false, 10));
}
catch (PropertyException exception)
{
exception.printStackTrace();
}
localProperties.add(new SelectionProperty("CarFollowingModel", "Car following model",
"The car following model determines "
+ "the acceleration that a vehicle will make taking into account "
+ "nearby vehicles, infrastructural restrictions (e.g. speed limit, "
+ "curvature of the road) capabilities of the vehicle and personality "
+ "of the driver.",
new String[] { "IDM", "IDM+" }, 1, false, 1));
localProperties.add(IDMPropertySet.makeIDMPropertySet("IDMCar", "Car",
new Acceleration(1.0, METER_PER_SECOND_2), new Acceleration(1.5, METER_PER_SECOND_2),
new Length(2.0, METER), new Duration(1.0, SECOND), 2));
localProperties.add(IDMPropertySet.makeIDMPropertySet("IDMTruck", "Truck",
new Acceleration(0.5, METER_PER_SECOND_2), new Acceleration(1.25, METER_PER_SECOND_2),
new Length(2.0, METER), new Duration(1.0, SECOND), 3));
sequential.buildAnimator(new Time(0.0, SECOND), new Duration(0.0, SECOND), new Duration(3600.0, SECOND),
localProperties, null, true);
sequential.panel.getTabbedPane().addTab("info", sequential.makeInfoPane());
}
catch (SimRuntimeException | NamingException | OTSSimulationException | PropertyException exception)
{
exception.printStackTrace();
}
}
});
}
/** {@inheritDoc} */
@Override
protected final void addAnimationToggles()
{
AnimationToggles.setTextAnimationTogglesStandard(this);
}
/** {@inheritDoc} */
@Override
protected final OTSModelInterface makeModel(final GTUColorer colorer)
{
this.model = new SequentialModel(this.savedUserModifiedProperties, colorer);
return this.model;
}
/**
* @return an info pane to be added to the tabbed pane.
*/
protected final JComponent makeInfoPane()
{
// Make the info tab
String helpSource = "/" + StraightModel.class.getPackage().getName().replace('.', '/') + "/IDMPlus.html";
URL page = StraightModel.class.getResource(helpSource);
if (page != null)
{
try
{
HTMLPanel htmlPanel = new HTMLPanel(page);
return new JScrollPane(htmlPanel);
}
catch (IOException exception)
{
exception.printStackTrace();
}
}
return new JPanel();
}
/** {@inheritDoc} */
@Override
protected final void addTabs(final SimpleSimulatorInterface simulator) throws OTSSimulationException, PropertyException
{
// Make the tab with the plots
Property> output = new CompoundProperty("", "", "", this.properties, false, 0).findByKey("OutputGraphs");
if (null == output)
{
throw new Error("Cannot find output properties");
}
ArrayList graphs = new ArrayList<>();
if (output instanceof CompoundProperty)
{
CompoundProperty outputProperties = (CompoundProperty) output;
for (Property> ap : outputProperties.getValue())
{
if (ap instanceof BooleanProperty)
{
BooleanProperty bp = (BooleanProperty) ap;
if (bp.getValue())
{
graphs.add(bp);
}
}
}
}
else
{
throw new Error("output properties should be compound");
}
int graphCount = graphs.size();
int columns = (int) Math.ceil(Math.sqrt(graphCount));
int rows = 0 == columns ? 0 : (int) Math.ceil(graphCount * 1.0 / columns);
TablePanel charts = new TablePanel(columns, rows);
for (int i = 0; i < graphCount; i++)
{
String graphName = graphs.get(i).getKey();
Container container = null;
LaneBasedGTUSampler graph;
if (graphName.contains("Trajectories"))
{
TrajectoryPlot tp =
new TrajectoryPlot("TrajectoryPlot", new Duration(0.5, SECOND), this.model.getPath(), simulator);
tp.setTitle("Trajectory Graph");
tp.setExtendedState(Frame.MAXIMIZED_BOTH);
graph = tp;
container = tp.getContentPane();
}
else
{
ContourPlot cp;
if (graphName.contains("Density"))
{
cp = new DensityContourPlot("DensityPlot", this.model.getPath());
cp.setTitle("Density Contour Graph");
}
else if (graphName.contains("Speed"))
{
cp = new SpeedContourPlot("SpeedPlot", this.model.getPath());
cp.setTitle("Speed Contour Graph");
}
else if (graphName.contains("Flow"))
{
cp = new FlowContourPlot("FlowPlot", this.model.getPath());
cp.setTitle("Flow Contour Graph");
}
else if (graphName.contains("Acceleration"))
{
cp = new AccelerationContourPlot("AccelerationPlot", this.model.getPath());
cp.setTitle("Acceleration Contour Graph");
}
else
{
continue;
// throw new Error("Unhandled type of contourplot: " + graphName);
}
graph = cp;
container = cp.getContentPane();
}
// Add the container to the matrix
charts.setCell(container, i % columns, i / columns);
this.model.getPlots().add(graph);
}
addTab(getTabCount(), "statistics", charts);
}
/** {@inheritDoc} */
@Override
public final String shortName()
{
return "Sequential Lanes";
}
/** {@inheritDoc} */
@Override
public final String description()
{
return "
Simulation of a straight one-lane road consisting of three consecutive Links
"
+ "Simulation of a single lane road consisting of two 1 km stretches with a 1m stretch in between. "
+ "This will test transition of a GTU from one lane section onto the next. "
+ "Vehicles are generated at a constant rate of 1500 veh/hour. "
+ "Selected trajectory and contour plots are generated during the simulation.";
}
}
/**
* Build the sequential model.
*
* Copyright (c) 2013-2016 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
*/
class SequentialModel implements OTSModelInterface, UNITS
{
/** */
private static final long serialVersionUID = 20150130L;
/** The simulator. */
private OTSDEVSSimulatorInterface simulator;
/** The network. */
private final OTSNetwork network = new OTSNetwork("network");
/** The nodes of our network in the order that all GTUs will visit them. */
private List nodes = new ArrayList<>();
/** The car following model, e.g. IDM Plus for cars. */
private GTUFollowingModelOld carFollowingModelCars;
/** The car following model, e.g. IDM Plus for trucks. */
private GTUFollowingModelOld carFollowingModelTrucks;
/** 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;
/** Type of all GTUs. */
private GTUType gtuType = CAR;
/** 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 contour plots. */
private List plots = new ArrayList<>();
/** The random number generator used to decide what kind of GTU to generate. */
private Random randomGenerator = new Random(12345);
/** User settable properties. */
private List> properties = null;
/** The sequence of Lanes that all vehicles will follow. */
private List path = new ArrayList<>();
/** The speedLimit on all Lanes. */
private Speed speedLimit;
/** The GTUColorer for the generated vehicles. */
private final GTUColorer gtuColorer;
/**
* @param properties the user settable properties
* @param gtuColorer the default and initial GTUColorer, e.g. a DefaultSwitchableTUColorer.
*/
SequentialModel(final List> properties, final GTUColorer gtuColorer)
{
this.properties = properties;
this.gtuColorer = gtuColorer;
}
/**
* @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(final SimulatorInterface