package org.opentrafficsim.imb.demo; import static org.opentrafficsim.road.gtu.lane.RoadGTUTypes.CAR; import java.awt.Color; import java.awt.Dimension; import java.awt.geom.Rectangle2D; import java.lang.reflect.InvocationTargetException; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Random; import java.util.Set; import javax.naming.NamingException; import javax.swing.JFrame; import javax.swing.SwingUtilities; import org.djunits.unit.DurationUnit; import org.djunits.unit.LengthUnit; import org.djunits.unit.TimeUnit; import org.djunits.unit.UNITS; import org.djunits.value.vdouble.scalar.Acceleration; 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.modelproperties.BooleanProperty; import org.opentrafficsim.base.modelproperties.CompoundProperty; import org.opentrafficsim.base.modelproperties.ContinuousProperty; import org.opentrafficsim.base.modelproperties.IntegerProperty; import org.opentrafficsim.base.modelproperties.ProbabilityDistributionProperty; import org.opentrafficsim.base.modelproperties.Property; import org.opentrafficsim.base.modelproperties.PropertyException; import org.opentrafficsim.base.modelproperties.SelectionProperty; import org.opentrafficsim.core.dsol.OTSDEVSRealTimeClock; import org.opentrafficsim.core.dsol.OTSDEVSSimulatorInterface; import org.opentrafficsim.core.dsol.OTSModelInterface; import org.opentrafficsim.core.dsol.OTSSimTimeDouble; import org.opentrafficsim.core.dsol.OTSSimulatorInterface; 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.gtu.RelativePosition; import org.opentrafficsim.core.gtu.animation.DefaultSwitchableGTUColorer; import org.opentrafficsim.core.gtu.animation.GTUColorer; import org.opentrafficsim.core.gtu.behavioralcharacteristics.BehavioralCharacteristics; 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.graphs.LaneBasedGTUSampler; import org.opentrafficsim.imb.IMBException; import org.opentrafficsim.imb.connector.IMBConnector; import org.opentrafficsim.imb.transceiver.urbanstrategy.GTUTransceiver; import org.opentrafficsim.imb.transceiver.urbanstrategy.LaneGTUTransceiver; import org.opentrafficsim.imb.transceiver.urbanstrategy.LinkGTUTransceiver; import org.opentrafficsim.imb.transceiver.urbanstrategy.NetworkTransceiver; import org.opentrafficsim.imb.transceiver.urbanstrategy.NodeTransceiver; import org.opentrafficsim.imb.transceiver.urbanstrategy.SensorGTUTransceiver; import org.opentrafficsim.imb.transceiver.urbanstrategy.SimulatorTransceiver; import org.opentrafficsim.road.gtu.animation.DefaultCarAnimation; import org.opentrafficsim.road.gtu.lane.LaneBasedGTU; import org.opentrafficsim.road.gtu.lane.LaneBasedIndividualGTU; import org.opentrafficsim.road.gtu.lane.tactical.LaneBasedCFLCTacticalPlannerFactory; import org.opentrafficsim.road.gtu.lane.tactical.following.AbstractIDM; import org.opentrafficsim.road.gtu.lane.tactical.following.GTUFollowingModelOld; import org.opentrafficsim.road.gtu.lane.tactical.following.IDMOld; import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusFactory; import org.opentrafficsim.road.gtu.lane.tactical.following.IDMPlusOld; import org.opentrafficsim.road.gtu.lane.tactical.lanechangemobil.AbstractLaneChangeModel; 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.lmrs.DefaultLMRSPerceptionFactory; import org.opentrafficsim.road.gtu.lane.tactical.lmrs.LMRSFactory; import org.opentrafficsim.road.gtu.lane.tactical.toledo.ToledoFactory; 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.modelproperties.IDMPropertySet; import org.opentrafficsim.road.network.animation.SensorAnimation; import org.opentrafficsim.road.network.factory.LaneFactory; import org.opentrafficsim.road.network.lane.CrossSectionElement; import org.opentrafficsim.road.network.lane.DirectedLanePosition; import org.opentrafficsim.road.network.lane.Lane; import org.opentrafficsim.road.network.lane.LaneType; import org.opentrafficsim.road.network.lane.object.LaneBasedObject; import org.opentrafficsim.road.network.lane.object.sensor.AbstractSensor; import nl.tno.imb.TConnection; import nl.tno.imb.mc.ModelParameters; import nl.tno.imb.mc.ModelStarter; import nl.tno.imb.mc.ModelState; import nl.tno.imb.mc.Parameter; import nl.tudelft.simulation.dsol.SimRuntimeException; import nl.tudelft.simulation.dsol.animation.D2.AnimationPanel; import nl.tudelft.simulation.dsol.experiment.Replication; import nl.tudelft.simulation.dsol.experiment.ReplicationMode; import nl.tudelft.simulation.dsol.simulators.AnimatorInterface; import nl.tudelft.simulation.dsol.simulators.Simulator; import nl.tudelft.simulation.dsol.simulators.SimulatorInterface; import nl.tudelft.simulation.event.Event; /** * Demonstrate an implementation of ModelEvent. *

* Copyright (c) 2013-2017 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 Oct 21, 2016
* @author Alexander Verbraeck * @author Peter Knoppers * @author Wouter Schakel */ public class ModelControlDemo extends ModelStarter { /** The thread that does the work. */ private CircularRoadIMB model = null; /** * @param args the command line arguments * @param providedModelName the model name * @param providedModelId the model id * @throws IMBException when connection with the IMB bus fails */ public ModelControlDemo(String[] args, String providedModelName, int providedModelId) throws IMBException { super(args, providedModelName, providedModelId); } /** * Find a particular property in a list of (compound) properties.
* Re-computing the keyPath is somewhat inefficient. Could be improved if we do not use the iterator of Property. * @param properties List<Property<?>>; the list * @param key String; the key path of the sought property * @return Property<?>; the first matching property, or null if no property with the given key was found */ private Property findPropertyInList(final List> properties, final String key) { try { CompoundProperty propertyContainer = new CompoundProperty("", "", "", properties, false, 0); for (Property p : propertyContainer) { String keyPath = p.getKey(); for (Property parent = p.getParent(); null != parent && propertyContainer != parent; parent = parent.getParent()) { keyPath = parent.getKey() + "." + keyPath; } // System.out.println("Comparing property key path " + keyPath + " to key " + key); if (key.equals(keyPath)) { return p; } } } catch (PropertyException exception) { exception.printStackTrace(); } return null; } /** {@inheritDoc} */ @Override public void startModel(final ModelParameters parameters, final TConnection tConnection) { System.out.println("startModel called"); System.out.println("parameters: " + parameters); System.out.println("Connection: " + this.connection); try { List> properties = new CircularRoadIMB(null, null, null, null).getSupportedProperties(); for (String parameterName : parameters.getParameterNames()) { if (parameterName.equals("Federation")) { continue; } else if (parameterName.equals("DataSource")) { continue; } int pos = parameterName.indexOf(" ("); if (pos < 0) { System.out.println("ignoring parameter " + parameterName); continue; } String strippedName = parameterName.substring(0, pos); switch (strippedName) { case "Truck fraction": { Property p = findPropertyInList(properties, "TrafficComposition"); if (null == p || !(p instanceof ProbabilityDistributionProperty)) { System.err.println("Property " + p + " is not a ProbalityDistributionProperty"); } else { ProbabilityDistributionProperty pdp = (ProbabilityDistributionProperty) p; Double[] values = pdp.getValue(); values[1] = (double) parameters.getParameterByName(parameterName).getValue(); values[0] = 1.0 - values[1]; try { System.out.println("Setting TrafficComposition to [" + values[0] + ", " + values[1] + "]"); pdp.setValue(values); } catch (PropertyException exception) { exception.printStackTrace(); } } break; } case "CACC penetration": { Property p = findPropertyInList(properties, "CACCpenetration"); if (null == p || !(p instanceof ContinuousProperty)) { System.err.println("Property " + p + " is not a ContinuousProperty"); } else { ContinuousProperty cp = (ContinuousProperty) p; Double value = (double) parameters.getParameterByName(parameterName).getValue(); try { System.out.println("Setting CACC penetration to " + value); cp.setValue(value); } catch (PropertyException exception) { exception.printStackTrace(); } } break; } case "CACC compliance": { Property p = findPropertyInList(properties, "CACCCompliance"); if (null == p || !(p instanceof ContinuousProperty)) { System.err.println("Property " + p + " is not a ContinuousProperty"); } else { ContinuousProperty cp = (ContinuousProperty) p; Double value = (double) parameters.getParameterByName(parameterName).getValue(); try { System.out.println("Setting CACC compliance to " + value); cp.setValue(value); } catch (PropertyException exception) { exception.printStackTrace(); } } break; } default: System.out.println("Ignoring parameter " + parameterName); break; } } IMBConnector simulationIMBConnector = new IMBConnector(this.connection); System.out.println("IMBConnector for simulation is " + simulationIMBConnector); this.model = new CircularRoadIMB(new DefaultSwitchableGTUColorer(), new OTSNetwork(""), properties, simulationIMBConnector); Replication replication = new Replication( "rep1", new OTSSimTimeDouble(Time.ZERO), Duration.ZERO, new Duration(1, DurationUnit.HOUR), this.model); OTSDEVSRealTimeClock simulator = new OTSDEVSRealTimeClock(); simulator.initialize(replication, ReplicationMode.TERMINATING); signalModelState(ModelState.READY); System.out.println("Reported ModelState.READY"); } catch (PropertyException | IMBException | NamingException | SimRuntimeException exception1) { exception1.printStackTrace(); } } /** {@inheritDoc} */ @Override public void stopModel() { System.out.println("stopModel called"); if (null != this.model) { try { ((Simulator) this.model.getSimulator()).cleanUp(); this.model.closeWindow(); this.model = null; } catch (RemoteException exception) { exception.printStackTrace(); } } else { System.err.println("stopModel called, but no model is running"); } } /** {@inheritDoc} */ @Override public void quitApplication() { if (null != this.model) { try { // clean up; even if stopModel was not called before quitApplication ((Simulator) this.model.getSimulator()).cleanUp(); } catch (Exception exception) { System.out.println("caught Exception in quitApplication:"); exception.printStackTrace(); } } System.out.println("quitApplication called"); } /** {@inheritDoc} */ @Override public void parameterRequest(ModelParameters parameters) { System.out.println("serving parameter request"); System.out.println("received parameters: " + parameters); try { List> propertyList = new CircularRoadIMB(null, null, null, null).getSupportedProperties(); Property truckFraction = findByKeyInList(propertyList, "TrafficComposition"); if (null != truckFraction) { parameters.addParameter(new Parameter("Truck fraction (range 0.0 - 1.0)", ((ProbabilityDistributionProperty) truckFraction).getValue()[1])); } Property caccPenetration = findByKeyInList(propertyList, "CACCpenetration"); if (null != caccPenetration) { parameters.addParameter( new Parameter("CACC penetration (range 0.0 - 1.0)", ((ContinuousProperty) caccPenetration).getValue())); } Property caccCompliance = findByKeyInList(propertyList, "CACCCompliance"); if (null != caccCompliance) { parameters.addParameter( new Parameter("CACC compliance (range 0.0 - 1.0)", ((ContinuousProperty) caccCompliance).getValue())); } System.out.println("(possibly) modified paramters: " + parameters); } catch (PropertyException exception) { exception.printStackTrace(); } } /** * Find a property with the specified key in a List of properties. * @param propertyList List<Property<?>>; the list * @param key String; the key * @return Property<?> or null if none of the entries in the list contained a property with the specified key */ private Property findByKeyInList(final List> propertyList, final String key) { Property result = null; for (Property property : propertyList) { Property p = property.findByKey(key); if (null != p) { if (null != result) { System.err.println("Duplicate property with key " + key + " in provided list"); } result = p; } } return result; } /** * Entry point. * @param args String[]; the command line arguments (not used) * @throws InvocationTargetException if an exception is thrown while running doRun * @throws InterruptedException if we're interrupted while waiting for the event dispatching thread to finish executing * doRun.run() */ public static void main(final String[] args) throws InvocationTargetException, InterruptedException { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { try { new ModelControlDemo(args, "Demo Model", 1234); } catch (IMBException exception) { exception.printStackTrace(); } } }); } /** * Simulate traffic on a circular, two-lane road. *

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

* $LastChangedDate: 2016-08-24 13:50:36 +0200 (Wed, 24 Aug 2016) $, @version $Revision: 2144 $, by $Author: pknoppers $, * initial version 1 nov. 2014
* @author Peter Knoppers */ static class CircularRoadIMB implements OTSModelInterface, UNITS { /** */ private static final long serialVersionUID = 20141121L; /** The simulator. */ private OTSDEVSSimulatorInterface simulator; /** Number of cars created. */ private int carsCreated = 0; /** 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 lane change model. */ private AbstractLaneChangeModel laneChangeModel; /** Minimum distance. */ private Length minimumDistance = new Length(0, METER); /** The speed limit. */ private Speed speedLimit = new Speed(100, KM_PER_HOUR); /** The plots. */ private List plots = new ArrayList(); /** User settable properties. */ private final List> properties; /** The sequence of Lanes that all vehicles will follow. */ private List> paths = new ArrayList<>(); /** The random number generator used to decide what kind of GTU to generate. */ private Random randomGenerator = new Random(12345); /** The GTUColorer for the generated vehicles. */ private final GTUColorer gtuColorer; /** Strategical planner generator for cars. */ private LaneBasedStrategicalPlannerFactory strategicalPlannerGeneratorCars = null; /** Strategical planner generator for cars. */ private LaneBasedStrategicalPlannerFactory strategicalPlannerGeneratorTrucks = null; /** the network as created by the AbstractWrappableIMBAnimation. */ private final OTSNetwork network; /** Connector to the IMB hub. */ private final IMBConnector imbConnector; /** The window with the animation. */ private JFrame frame; /** * @param gtuColorer the default and initial GTUColorer, e.g. a DefaultSwitchableTUColorer. * @param network Network; the network * @param properties AbstractProperty; properties that configure this simulation * @param imbConnector IMBConnector; connection to the IMB hub * @throws PropertyException XXX not thrown */ CircularRoadIMB(final GTUColorer gtuColorer, final OTSNetwork network, final List> properties, final IMBConnector imbConnector) throws PropertyException { this.properties = properties; this.gtuColorer = gtuColorer; this.network = network; this.imbConnector = imbConnector; } /** * Construct and return the list of properties that the user may modify. * @return List<AbstractProperty>; the list of properties that the user may modify */ public List> getSupportedProperties() { List> result = new ArrayList<>(); result.add(new ContinuousProperty("CACCpenetration", "CACC penetration", "Fraction of vehicles equipped with CACC", 0.0, 0.0, 1.0, "%.2f", false, 13)); result.add(new ContinuousProperty("CACCCompliance", "CACC compliance", "Compliance within CADD equipped vehicle population", 0.5, 0.0, 1.0, "%.2f", false, 14)); result.add(new SelectionProperty("LaneChanging", "Lane changing", "The lane change strategies vary in politeness.
" + "Two types are implemented: