package org.opentrafficsim.imb.transceiver.urbanstrategy; import java.util.ArrayList; import java.util.List; import org.djunits.unit.SpeedUnit; import org.djunits.unit.TimeUnit; import org.djunits.value.vdouble.scalar.Dimensionless; 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.core.dsol.OTSSimulatorInterface; import org.opentrafficsim.imb.IMBException; import org.opentrafficsim.imb.connector.Connector; import org.opentrafficsim.imb.connector.Connector.IMBEventType; import org.opentrafficsim.imb.transceiver.AbstractTransceiver; import org.opentrafficsim.kpi.interfaces.GtuDataInterface; import org.opentrafficsim.kpi.sampling.Query; import org.opentrafficsim.kpi.sampling.TrajectoryGroup; import org.opentrafficsim.kpi.sampling.indicator.MeanSpeed; import org.opentrafficsim.kpi.sampling.indicator.MeanTravelTimePerDistance; import org.opentrafficsim.kpi.sampling.indicator.MeanTripLength; import org.opentrafficsim.kpi.sampling.indicator.TotalDelay; import org.opentrafficsim.kpi.sampling.indicator.TotalNumberOfStops; import org.opentrafficsim.kpi.sampling.indicator.TotalTravelDistance; import org.opentrafficsim.kpi.sampling.indicator.TotalTravelTime; import org.opentrafficsim.road.network.sampling.data.ReferenceSpeed; import org.opentrafficsim.road.network.sampling.indicator.TotalDelayReference; import nl.tudelft.simulation.dsol.SimRuntimeException; /** * OTS can publish messages about statistics or Key Performance Indicators (KPIs) of the relation between GTUs and a part of the * network. Examples are average speeds, travel times, trip durations, and number of stops. The statistics can be transmitted * via IMB at certain intervals. The statistics are based on the classes in the ots.road.sampling package. Most statistics * consider a time interval (can be unbound) and a region in space (a collection of lanes; can be the entire network), filtered * on metadata such as GTU type, origin, destination, or route.
* When a statistic is published for the first time, a NEW message is sent to IMB to identify the type of statistic, the time * interval and the lane(s) for which the statistic is calculated, and the metadata used to filter the GTUs. The CHANGE message * is posted whenever an updated statistic is available, or when the sample frequency time is reached. When a statistic is no * longer published, a DELETE event is posted. The Graph NEW messages are posted after the Network NEW, Node NEW, Link NEW, and * Lane NEW messages are posted, as it has to be able to identify Lanes. *

* *

NEW

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
VariableTypeComments
timestampdoubletime of the event, in simulation time seconds
statisticIdStringa unique id for the statistic, e.g. a UUID string
descriptionStringtextual description of the statistic
networkIdStringid of the Network for which the statistic is made
numberMetadataEntriesintnumber of metadata entries
metadataId_1Stringid of the first metadata entry
metadataType_1Stringtype of metadata, one of GTUTYPE, ORIGIN, DESTINATION, ROUTE
metadataValue_1Stringvalue of the first metadata entry
...  
metadataId_nStringid of the last metadata entry
metadataType_nStringtype of metadata, one of GTUTYPE, ORIGIN, DESTINATION, ROUTE
metadataValue_nStringvalue of the last metadata entry
numberSpaceTimeRegionsintnumber of space-time regions for this statistic
startTime_1doublestart time for the first space time region, in seconds
endTime_1doubleend time for the first space time region, in seconds
linkId_1Stringid of the first Link for the space-time region
laneId_1Stringid of the first Lane in the link for the space-time region
...  
startTime_ndoublestart time for the last space time region, in seconds
endTime_ndoubleend time for the last space time region, in seconds
linkId_nStringid of the last Link for the space-time region
laneId_nStringid of the last Lane in the link for the space-time region
connectedbooleanwhether the lanes in the space-time regions are longitudinally connected or not
transmissionIntervaldoubletransmission interval of the statistic in seconds
*

*

*

CHANGE

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
VariableTypeComments
timestampdoubletime of the event, in simulation time seconds
statisticIdStringthe unique id for the statistic, e.g. a UUID string
totalGtuDistancedoubletotal distance traveled by filtered GTUs in the given time and space, in meters
totalGtuTravelTimedoubletotal travel time by filtered GTUs in the given time and space, in seconds
averageGtuSpeeddoubleaverage filtered GTU speed in the given time and space, in meter/second
averageGtuTravelTimePerDistancedoubleaverage filtered GTU travel time in the given time and space, in seconds per km
totalGtuTimeDelaydoubletotal time delay incurred by the filtered GTUs in the given time and space, in seconds
averageTripLengthdoubleaverage length of the trip of the filtered GTUs in the given time and space, in seconds
totalNumberStopsdoubletotal number of stops that GTUs made in the given time and space, dimensionless
*

*

*

DELETE

* * * * * * * * * * * * * * * * * * * *
VariableTypeComments
timestampdoubletime of the event, in simulation time seconds
statisticIdStringthe unique id for the statistic that is removed
*

*

* Copyright (c) 2013-2019 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 Sep 16, 2016
* @author Alexander Verbraeck * @author Peter Knoppers * @param gtu data type */ public class StatisticsGTULaneTransceiver extends AbstractTransceiver { /** */ private static final long serialVersionUID = 20160923L; /** Reference speed extended data type. */ static final ReferenceSpeed REF_SPEED_TYPE = new ReferenceSpeed(); /** The query for the statistic. */ final Query query; /** The Network id for which the graph is made. */ private final String networkId; /** The interval between generation of graphs. */ final Duration transmissionInterval; /** Total travel distance. */ TotalTravelDistance totalTravelDistance = new TotalTravelDistance(); /** Total travel time. */ TotalTravelTime totalTravelTime = new TotalTravelTime(); /** Mean speed. */ MeanSpeed meanSpeed = new MeanSpeed(this.totalTravelDistance, this.totalTravelTime); /** Mean travel time per km. */ MeanTravelTimePerDistance meanTravelTimePerDistance = new MeanTravelTimePerDistance(this.meanSpeed); /** Mean trip length. */ MeanTripLength meanTripLength = new MeanTripLength(); /** Total delay. */ TotalDelay totalDelay = new TotalDelay(new Speed(80.0, SpeedUnit.KM_PER_HOUR)); /** Total delay with reference. */ TotalDelayReference totalDelayReference = new TotalDelayReference(); /** Total number of stops. */ TotalNumberOfStops totalNumberOfStops = new TotalNumberOfStops(); // TODO implement DELETE message /** * Construct a new StatisticsGTULaneTransceiver. * @param connector Connector; the IMB connector * @param simulator OTSSimulatorInterface; the simulator * @param networkId String; the network id * @param query Query<G>; the statistics query * @param transmissionInterval Duration; the interval between generation of graphs * @throws IMBException when the message cannot be posted, or the scheduling of the publish event fails */ public StatisticsGTULaneTransceiver(final Connector connector, OTSSimulatorInterface simulator, String networkId, final Query query, final Duration transmissionInterval) throws IMBException { super("StatisticsGTULane", connector, simulator); this.query = query; this.networkId = networkId; this.transmissionInterval = transmissionInterval; List newMessage = new ArrayList<>(); newMessage.add(getSimulator().getSimulatorTime().si); newMessage.add(query.getId()); newMessage.add(query.toString()); newMessage.add(this.networkId); newMessage.add(0); // TODO numberMetadataEntries newMessage.add(0); // TODO numberSpaceTimeRegions newMessage.add(false); // TODO "connected" not part of query anymore newMessage.add(true); // TODO totalTrajectory newMessage.add(transmissionInterval.si); getConnector().postIMBMessage("StatisticsGTULane", IMBEventType.NEW, newMessage.toArray()); try { simulator.scheduleEventRel(this.transmissionInterval, this, this, "sendStatisticsUpdate", new Object[] {}); } catch (SimRuntimeException exception) { throw new IMBException(exception); } } /** * @throws IMBException when the transmission of the IMB message fails * @throws SimRuntimeException when the scheduling of the next publish event fails */ public void sendStatisticsUpdate() throws IMBException, SimRuntimeException { double time = getSimulator().getSimulatorTime().si; Query q = StatisticsGTULaneTransceiver.this.query; Time timeObject = new Time(time, TimeUnit.BASE_SECOND); List> groups = q.getTrajectoryGroups(timeObject); Length tdist = StatisticsGTULaneTransceiver.this.totalTravelDistance.getValue(q, timeObject, groups); Duration ttt = StatisticsGTULaneTransceiver.this.totalTravelTime.getValue(q, timeObject, groups); Speed ms = StatisticsGTULaneTransceiver.this.meanSpeed.getValue(q, timeObject, groups); Duration mttpdist = StatisticsGTULaneTransceiver.this.meanTravelTimePerDistance.getValue(q, timeObject, groups); Length mtl = StatisticsGTULaneTransceiver.this.meanTripLength.getValue(q, timeObject, groups); Duration tdel; if (q.getSampler().contains(REF_SPEED_TYPE)) { tdel = StatisticsGTULaneTransceiver.this.totalDelayReference.getValue(q, timeObject, groups); } else { tdel = StatisticsGTULaneTransceiver.this.totalDelay.getValue(q, timeObject, groups); } Dimensionless nos = StatisticsGTULaneTransceiver.this.totalNumberOfStops.getValue(q, timeObject, groups); System.out.println("===== @time " + time + " s on " + q.getId() + " ====="); System.out.println("Total distance " + tdist); System.out.println("Total travel time " + ttt); System.out.println("Mean speed " + ms); System.out.println("Mean travel time " + mttpdist + " (per m)"); System.out.println("Mean trip length " + mtl); System.out.println("Total delay " + tdel); System.out.println("Number of stops " + nos); getConnector().postIMBMessage("StatisticsGTULane", IMBEventType.CHANGE, new Object[] {time, q.getId(), tdist.si, ttt.si, ms.si, mttpdist.si, tdel.si, mtl.si, nos.si}); // Thread thread = new Thread(new StatisticsRunnable(time, groups), "Statistics calculation thread"); // thread.start(); getSimulator().scheduleEventRel(StatisticsGTULaneTransceiver.this.transmissionInterval, StatisticsGTULaneTransceiver.this, StatisticsGTULaneTransceiver.this, "sendStatisticsUpdate", new Object[] {}); } /** *

* Copyright (c) 2013-2019 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 29 nov. 2016
* @author Alexander Verbraeck * @author Peter Knoppers * @author Wouter Schakel */ class StatisticsRunnable implements Runnable { /** Time of statistics. */ private final double time; /** Trajectory groups. */ private List> sourceGroups; /** * @param time double; time of statistics */ public StatisticsRunnable(final double time) { this.time = time; } /** * @param time double; time of statistics * @param sourceGroups List<TrajectoryGroup<G>>; groups */ public StatisticsRunnable(final double time, final List> sourceGroups) { this.time = time; this.sourceGroups = sourceGroups; } @Override public void run() { Query q = StatisticsGTULaneTransceiver.this.query; Time timeObject = new Time(this.time, TimeUnit.BASE_SECOND); List> groups = this.sourceGroups == null ? q.getTrajectoryGroups(timeObject) : this.sourceGroups; Length tdist = StatisticsGTULaneTransceiver.this.totalTravelDistance.getValue(q, timeObject, groups); Duration ttt = StatisticsGTULaneTransceiver.this.totalTravelTime.getValue(q, timeObject, groups); Speed ms = StatisticsGTULaneTransceiver.this.meanSpeed.getValue(q, timeObject, groups); Duration mttpdist = StatisticsGTULaneTransceiver.this.meanTravelTimePerDistance.getValue(q, timeObject, groups); Length mtl = StatisticsGTULaneTransceiver.this.meanTripLength.getValue(q, timeObject, groups); Duration tdel; if (q.getSampler().contains(REF_SPEED_TYPE)) { tdel = StatisticsGTULaneTransceiver.this.totalDelayReference.getValue(q, timeObject, groups); } else { tdel = StatisticsGTULaneTransceiver.this.totalDelay.getValue(q, timeObject, groups); } Dimensionless nos = StatisticsGTULaneTransceiver.this.totalNumberOfStops.getValue(q, timeObject, groups); System.out.println("===== @time " + this.time + " s on " + q.getId() + " ====="); System.out.println("Total distance " + tdist); System.out.println("Total travel time " + ttt); System.out.println("Mean speed " + ms); System.out.println("Mean travel time " + mttpdist + " (per m)"); System.out.println("Mean trip length " + mtl); System.out.println("Total delay " + tdel); System.out.println("Number of stops " + nos); try { getConnector().postIMBMessage("StatisticsGTULane", IMBEventType.CHANGE, new Object[] {this.time, q.getId(), tdist.si, ttt.si, ms.si, mttpdist.si, tdel.si, mtl.si, nos.si}); } catch (IMBException exception) { exception.printStackTrace(); } } } }