package org.opentrafficsim.demo.lanechange; import java.awt.BorderLayout; import java.awt.Frame; import java.awt.geom.Line2D; import java.lang.reflect.InvocationTargetException; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Set; import javax.naming.NamingException; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.event.EventListenerList; import nl.tudelft.simulation.dsol.SimRuntimeException; import nl.tudelft.simulation.dsol.gui.swing.TablePanel; import nl.tudelft.simulation.dsol.simulators.SimulatorInterface; import org.djunits.unit.TimeUnit; import org.djunits.unit.UNITS; import org.djunits.value.vdouble.scalar.Acceleration; import org.djunits.value.vdouble.scalar.DoubleScalar; import org.djunits.value.vdouble.scalar.DoubleScalar.Abs; import org.djunits.value.vdouble.scalar.Length; import org.djunits.value.vdouble.scalar.Speed; import org.djunits.value.vdouble.scalar.Time; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.StandardChartTheme; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.event.PlotChangeEvent; import org.jfree.chart.plot.Plot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.DomainOrder; import org.jfree.data.general.DatasetChangeListener; import org.jfree.data.general.DatasetGroup; import org.jfree.data.xy.XYDataset; import org.opentrafficsim.core.dsol.OTSModelInterface; import org.opentrafficsim.core.dsol.OTSSimTimeDouble; import org.opentrafficsim.core.geometry.OTSGeometryException; 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.LongitudinalDirectionality; import org.opentrafficsim.core.network.NetworkException; import org.opentrafficsim.core.network.OTSNetwork; import org.opentrafficsim.core.network.OTSNode; import org.opentrafficsim.road.car.LaneBasedIndividualCar; import org.opentrafficsim.road.gtu.lane.driver.LaneBasedDrivingCharacteristics; import org.opentrafficsim.road.gtu.lane.perception.LanePerceptionFull; import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlanner; import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModel; import org.opentrafficsim.road.gtu.lane.tactical.following.HeadwayGTU; import org.opentrafficsim.road.gtu.lane.tactical.following.IDM; import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlus; import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Altruistic; import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.Egoistic; import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneChangeModel; import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.LaneMovementStep; import org.opentrafficsim.road.gtu.strategical.LaneBasedStrategicalPlanner; import org.opentrafficsim.road.gtu.strategical.route.LaneBasedStrategicalRoutePlanner; import org.opentrafficsim.road.network.factory.LaneFactory; import org.opentrafficsim.road.network.lane.DirectedLanePosition; import org.opentrafficsim.road.network.lane.Lane; import org.opentrafficsim.road.network.lane.LaneType; import org.opentrafficsim.simulationengine.SimpleSimulator; /** * Create a plot that characterizes a lane change graph. *
* Copyright (c) 2013-2015 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 18 nov. 2014
* @author Peter Knoppers
*/
public class LaneChangeGraph extends JFrame implements OTSModelInterface, UNITS
{
/** */
private static final long serialVersionUID = 20141118L;
/** Standard speed values in km/h. */
static final double[] STANDARDSPEEDS = {30, 50, 80, 100, 120};
/** The car following model. */
private GTUFollowingModel carFollowingModel;
/** The graphs. */
private ChartPanel[][] charts;
/** Start of two lane road. */
private static final Length.Rel LOWERBOUND = new Length.Rel(-500, METER);
/** Position of reference vehicle on the two lane road. */
private static final Length.Rel MIDPOINT = new Length.Rel(0, METER);
/** End of two lane road. */
private static final Length.Rel UPPERBOUND = new Length.Rel(500, METER);
/** The JFrame with the lane change graphs. */
private static LaneChangeGraph lcs;
/** network. */
private OTSNetwork network = new OTSNetwork("network");
/**
* Create a Lane Change Graph.
* @param title String; title text of the window
* @param mainPanel JPanel; panel that will (indirectly?) contain the charts
*/
LaneChangeGraph(final String title, final JPanel mainPanel)
{
super(title);
setContentPane(mainPanel);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.charts = new ChartPanel[2][STANDARDSPEEDS.length];
}
/**
* Main entry point; now Swing thread safe (I hope).
* @param args String[]; the command line arguments (not used)
* @throws GTUException on error during GTU construction
* @throws SimRuntimeException on ???
* @throws NetworkException on network inconsistency
* @throws NamingException on ???
* @throws OTSGeometryException
*/
public static void main(final String[] args) throws NamingException, NetworkException, SimRuntimeException,
GTUException, OTSGeometryException
{
try
{
SwingUtilities.invokeAndWait(new Runnable()
{
@Override
public void run()
{
try
{
buildGUI(args);
}
catch (NamingException | NetworkException | SimRuntimeException | GTUException exception)
{
exception.printStackTrace();
}
}
});
}
catch (InvocationTargetException | InterruptedException exception)
{
exception.printStackTrace();
}
for (int row = 0; row < lcs.charts.length; row++)
{
LaneChangeModel laneChangeModel = 0 == row ? new Egoistic() : new Altruistic();
for (int index = 0; index < STANDARDSPEEDS.length; index++)
{
Speed speed = new Speed(STANDARDSPEEDS[index], KM_PER_HOUR);
// System.out.println("speed " + speed);
double startSpeedDifference = -30; // standardSpeeds[index];
double endSpeedDifference = startSpeedDifference + 60; // 150;
ChartData data = (ChartData) lcs.charts[row][index].getChart().getXYPlot().getDataset();
int beginRightKey = data.addSeries("Begin of no lane change to right");
int endRightKey = data.addSeries("End of no lane change to right");
int beginLeftKey = data.addSeries("Begin of no lane change to left");
int endLeftKey = data.addSeries("End of no lane change to left");
for (double speedDifference = startSpeedDifference; speedDifference <= endSpeedDifference; speedDifference +=
1)
{
Length.Rel criticalHeadway =
lcs.findDecisionPoint(LaneChangeGraph.LOWERBOUND, MIDPOINT, speed, new Speed(speedDifference,
KM_PER_HOUR), laneChangeModel, true);
if (null != criticalHeadway)
{
data.addXYPair(beginRightKey, speedDifference, criticalHeadway.getInUnit(METER));
}
criticalHeadway =
lcs.findDecisionPoint(MIDPOINT, LaneChangeGraph.UPPERBOUND, speed, new Speed(speedDifference,
KM_PER_HOUR), laneChangeModel, true);
if (null != criticalHeadway)
{
data.addXYPair(endRightKey, speedDifference, criticalHeadway.getInUnit(METER));
}
criticalHeadway =
lcs.findDecisionPoint(LaneChangeGraph.LOWERBOUND, MIDPOINT, speed, new Speed(speedDifference,
KM_PER_HOUR), laneChangeModel, false);
if (null != criticalHeadway)
{
data.addXYPair(beginLeftKey, speedDifference, criticalHeadway.getInUnit(METER));
}
else
{
lcs.findDecisionPoint(LaneChangeGraph.LOWERBOUND, MIDPOINT, speed, new Speed(speedDifference,
KM_PER_HOUR), laneChangeModel, false);
}
criticalHeadway =
lcs.findDecisionPoint(MIDPOINT, LaneChangeGraph.UPPERBOUND, speed, new Speed(speedDifference,
KM_PER_HOUR), laneChangeModel, false);
if (null != criticalHeadway)
{
data.addXYPair(endLeftKey, speedDifference, criticalHeadway.getInUnit(METER));
}
Plot plot = lcs.charts[row][index].getChart().getPlot();
plot.notifyListeners(new PlotChangeEvent(plot));
}
}
}
}
/**
* Then execution start point.
* @param args String[]; the command line arguments (not used)
* @throws NamingException on ???
* @throws NetworkException on network inconsistency
* @throws SimRuntimeException on ???
* @throws GTUException on error during GTU construction
*/
public static void buildGUI(final String[] args) throws NamingException, NetworkException, SimRuntimeException,
GTUException
{
JPanel mainPanel = new JPanel(new BorderLayout());
lcs = new LaneChangeGraph("Lane change graphs", mainPanel);
TablePanel chartsPanel = new TablePanel(STANDARDSPEEDS.length, 2);
mainPanel.add(chartsPanel, BorderLayout.CENTER);
for (int index = 0; index < STANDARDSPEEDS.length; index++)
{
lcs.charts[0][index] =
new ChartPanel(lcs.createChart(
String.format("Egoistic reference car at %.0fkm/h", STANDARDSPEEDS[index]), STANDARDSPEEDS[index]));
chartsPanel.setCell(lcs.charts[0][index], index, 0);
}
for (int index = 0; index < STANDARDSPEEDS.length; index++)
{
lcs.charts[1][index] =
new ChartPanel(
lcs.createChart(String.format("Altruistic reference car at %.0fkm/h", STANDARDSPEEDS[index]),
STANDARDSPEEDS[index]));
chartsPanel.setCell(lcs.charts[1][index], index, 1);
}
lcs.pack();
lcs.setExtendedState(Frame.MAXIMIZED_BOTH);
lcs.setVisible(true);
}
/**
* Find the headway at which the decision to merge right changes.
* @param low minimum headway to consider
* @param high maximum headway to consider
* @param referenceSpeed Speed; speed of the reference car
* @param speedDifference Speed; speed of the other car minus speed of the reference car
* @param laneChangeModel LaneChangeModel; the lane change model to apply
* @param mergeRight boolean; if true; merge right is tested; if false; merge left is tested
* @return Length.Rel
* @throws NamingException on ???
* @throws NetworkException on network inconsistency
* @throws SimRuntimeException on ???
* @throws GTUException on error during GTU construction
* @throws OTSGeometryException
*/
private Length.Rel findDecisionPoint(Length.Rel low, Length.Rel high, final Speed referenceSpeed,
final Speed speedDifference, final LaneChangeModel laneChangeModel, final boolean mergeRight)
throws NamingException, NetworkException, SimRuntimeException, GTUException, OTSGeometryException
{
// Set up the network
GTUType gtuType = GTUType.makeGTUType("car");
LaneType laneType = new LaneType("CarLane");
laneType.addCompatibility(gtuType);
final Speed speedLimit = new Speed(120, KM_PER_HOUR);
Lane[] lanes =
LaneFactory.makeMultiLane("Road with two lanes", new OTSNode("From", new OTSPoint3D(LOWERBOUND.getSI(), 0,
0)), new OTSNode("To", new OTSPoint3D(UPPERBOUND.getSI(), 0, 0)), null, 2, laneType, speedLimit, null,
LongitudinalDirectionality.DIR_PLUS);
// Create the reference vehicle
Set