package org.opentrafficsim.swing.script; import java.awt.Dimension; import java.rmi.RemoteException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.djunits.value.vdouble.scalar.Duration; import org.djunits.value.vdouble.scalar.Time; import org.djutils.cli.Checkable; import org.djutils.cli.CliException; import org.djutils.cli.CliUtil; import org.djutils.event.EventInterface; import org.djutils.event.EventListenerInterface; import org.djutils.exceptions.Throw; import org.djutils.exceptions.Try; import org.djutils.reflection.ClassUtil; import org.opentrafficsim.core.animation.gtu.colorer.GTUColorer; import org.opentrafficsim.core.dsol.OTSAnimator; import org.opentrafficsim.core.dsol.OTSModelInterface; import org.opentrafficsim.core.dsol.OTSSimulator; import org.opentrafficsim.core.dsol.OTSSimulatorInterface; import org.opentrafficsim.core.network.OTSNetwork; import org.opentrafficsim.draw.core.OTSDrawingException; import org.opentrafficsim.draw.factory.DefaultAnimationFactory; import org.opentrafficsim.road.network.OTSRoadNetwork; import org.opentrafficsim.swing.gui.AnimationToggles; import org.opentrafficsim.swing.gui.OTSAnimationPanel; import org.opentrafficsim.swing.gui.OTSSimulationApplication; import org.opentrafficsim.swing.gui.OTSSwingApplication; import nl.tudelft.simulation.dsol.SimRuntimeException; import nl.tudelft.simulation.dsol.experiment.ReplicationInterface; import nl.tudelft.simulation.dsol.experiment.StreamInformation; import nl.tudelft.simulation.dsol.model.inputparameters.InputParameterMap; import nl.tudelft.simulation.dsol.simtime.SimTimeDoubleUnit; import nl.tudelft.simulation.dsol.statistics.StatisticsInterface; import nl.tudelft.simulation.jstats.streams.MersenneTwister; import nl.tudelft.simulation.jstats.streams.StreamInterface; import picocli.CommandLine.Command; import picocli.CommandLine.Option; /** * Template for simulation script. This class allows the user to run a single visualized simulation, or to batch-run the same * model. Parameters can be given through the command-line using djutils-ext. Fields can be added to sub-classes using the * {@code @Options} and similar annotations. Default values of the properties in this abstract class can be overwritten by the * sub-class using {@code CliUtil.changeDefaultValue()}. *
* Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License.
*
* @version $Revision$, $LastChangedDate$, by $Author$, initial version 9 apr. 2018
* Copyright (c) 2013-2022 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
*
* @version $Revision$, $LastChangedDate$, by $Author$, initial version 9 apr. 2018
* @author Alexander Verbraeck
* @author Peter Knoppers
* @author Wouter Schakel
*/
@Command(description = "Test program for CLI", name = "Program", mixinStandardHelpOptions = true, showDefaultValues = true)
public abstract class AbstractSimulationScript implements EventListenerInterface, Checkable
{
/** */
private static final long serialVersionUID = 20200129L;
/** Name. */
private final String name;
/** Description. */
private final String description;
/** The simulator. */
private OTSSimulatorInterface simulator;
/** The network. */
private OTSRoadNetwork network;
/** GTU colorer. */
private GTUColorer gtuColorer = OTSSwingApplication.DEFAULT_COLORER;
/** Seed. */
@Option(names = "--seed", description = "Seed", defaultValue = "1")
private long seed;
/** Start time. */
@Option(names = { "-s", "--startTime" }, description = "Start time", defaultValue = "0s")
private Time startTime;
/** Warm-up time. */
@Option(names = { "-w", "--warmupTime" }, description = "Warm-up time", defaultValue = "0s")
private Duration warmupTime;
/** Simulation time. */
@Option(names = { "-t", "--simulationTime" }, description = "Simulation time (including warm-up time)",
defaultValue = "3600s")
private Duration simulationTime;
/** Autorun. */
@Option(names = { "-a", "--autorun" }, description = "Autorun", negatable = true, defaultValue = "false")
private boolean autorun;
/**
* Constructor.
* @param name String; name
* @param description String; description
*/
protected AbstractSimulationScript(final String name, final String description)
{
this.name = name;
this.description = description;
try
{
CliUtil.changeCommandName(this, this.name);
CliUtil.changeCommandDescription(this, this.description);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
CliUtil.changeCommandVersion(this,
formatter.format(new Date(ClassUtil.classFileDescriptor(this.getClass()).getLastChangedDate())));
}
catch (IllegalStateException | IllegalArgumentException | CliException exception)
{
throw new RuntimeException("Exception while setting properties in @Command annotation.", exception);
}
}
/**
* Returns the seed.
* @return long; seed
*/
public long getSeed()
{
return this.seed;
}
/**
* Returns the start time.
* @return Time; start time
*/
public Time getStartTime()
{
return this.startTime;
}
/**
* Returns the warm-up time.
* @return Duration; warm-up time
*/
public Duration getWarmupTime()
{
return this.warmupTime;
}
/**
* Returns the simulation time.
* @return Duration; simulation time
*/
public Duration getSimulationTime()
{
return this.simulationTime;
}
/**
* Returns whether to autorun.
* @return boolean; whether to autorun
*/
public boolean isAutorun()
{
return this.autorun;
}
/**
* Set GTU colorer.
* @param colorer GTUColorer; GTU colorer
*/
public final void setGtuColorer(final GTUColorer colorer)
{
this.gtuColorer = colorer;
}
/**
* Returns the GTU colorer.
* @return returns the GTU colorer
*/
public final GTUColorer getGtuColorer()
{
return this.gtuColorer;
}
/** {@inheritDoc} */
@Override
public void check() throws Exception
{
Throw.when(this.seed < 0, IllegalArgumentException.class, "Seed should be positive");
Throw.when(this.warmupTime.si < 0.0, IllegalArgumentException.class, "Warm-up time should be positive");
Throw.when(this.simulationTime.si < 0.0, IllegalArgumentException.class, "Simulation time should be positive");
Throw.when(this.simulationTime.si < this.warmupTime.si, IllegalArgumentException.class,
"Simulation time should be longer than warmp-up time");
}
/**
* Starts the simulation.
* @throws Exception on any exception
*/
public final void start() throws Exception
{
if (isAutorun())
{
// TODO: wait until simulation control buttons are enabled (indicating that the tabs have been added)
this.simulator = new OTSSimulator(this.name);
final ScriptModel scriptModel = new ScriptModel(this.simulator);
this.simulator.initialize(this.startTime, this.warmupTime, this.simulationTime, scriptModel);
this.simulator.addListener(this, ReplicationInterface.END_REPLICATION_EVENT);
double tReport = 60.0;
Time t = this.simulator.getSimulatorTime();
while (t.si < this.simulationTime.si)
{
this.simulator.step();
t = this.simulator.getSimulatorTime();
if (t.si >= tReport)
{
System.out.println("Simulation time is " + t);
tReport += 60.0;
}
}
// sim.stop(); // end of simulation event
onSimulationEnd(); // TODO this is temporary for as long as stop() gives an exception
System.exit(0);
}
else
{
this.simulator = new OTSAnimator(this.name);
final ScriptModel scriptModel = new ScriptModel(this.simulator);
this.simulator.initialize(this.startTime, this.warmupTime, this.simulationTime, scriptModel);
OTSAnimationPanel animationPanel =
new OTSAnimationPanel(scriptModel.getNetwork().getExtent(), new Dimension(800, 600),
(OTSAnimator) this.simulator, scriptModel, getGtuColorer(), scriptModel.getNetwork());
setAnimationToggles(animationPanel);
animateNetwork(scriptModel.getNetwork());
setupDemo(animationPanel, scriptModel.getNetwork());
OTSSimulationApplication
* BSD-style license. See OpenTrafficSim License.
*
* @author Alexander Verbraeck
* @author Peter Knoppers
* @author Wouter Schakel
*/
private class ScriptModel implements OTSModelInterface
{
/** */
private static final long serialVersionUID = 20180409L;
/**
* @param simulator OTSSimulatorInterface; the simulator
*/
@SuppressWarnings("synthetic-access")
ScriptModel(final OTSSimulatorInterface simulator)
{
AbstractSimulationScript.this.simulator = simulator;
}
/** {@inheritDoc} */
@SuppressWarnings("synthetic-access")
@Override
public void constructModel() throws SimRuntimeException
{
Map