package org.opentrafficsim.imb.kpi; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.djunits.unit.SpeedUnit; 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.imb.IMBException; import org.opentrafficsim.imb.connector.Connector; import org.opentrafficsim.imb.connector.Connector.IMBEventType; 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; /** * 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 daat type */ public class ImbKpiTransceiver implements Serializable { /** */ private static final long serialVersionUID = 20160923L; /** IMB connector. */ private final Connector connector; /** The query for the statistic. */ private final Query query; /** The Network id for which the graph is made. */ private final String networkId; /** The interval between generation of graphs. */ private final Duration transmissionInterval; /** Total travel distance. */ private TotalTravelDistance totalTravelDistance = new TotalTravelDistance(); /** Total travel time. */ private TotalTravelTime totalTravelTime = new TotalTravelTime(); /** Mean speed. */ private MeanSpeed meanSpeed = new MeanSpeed(this.totalTravelDistance, this.totalTravelTime); /** Mean travel time per km. */ private MeanTravelTimePerDistance meanTravelTimePerDistance = new MeanTravelTimePerDistance(this.meanSpeed); /** Mean trip length. */ private MeanTripLength meanTripLength = new MeanTripLength(); /** Total delay. */ private TotalDelay totalDelay = new TotalDelay(new Speed(50.0, SpeedUnit.KM_PER_HOUR)); /** Total number of stops. */ private TotalNumberOfStops totalNumberOfStops = new TotalNumberOfStops(); /** Update time. */ private Time updateTime = Time.ZERO; // TODO implement DELETE message /** * Construct a new ImbKpiTransceiver. * @param connector Connector; the IMB connector * @param time Time; time of creation * @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 post of the IMB message fails */ public ImbKpiTransceiver(final Connector connector, Time time, String networkId, final Query query, final Duration transmissionInterval) throws IMBException { this.connector = connector; this.query = query; this.networkId = networkId; this.transmissionInterval = transmissionInterval; List newMessage = new ArrayList<>(); newMessage.add(time.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); this.connector.postIMBMessage("StatisticsGTULane", IMBEventType.NEW, newMessage.toArray()); sendStatisticsUpdate(); } /** * Notifies about time, such that statistics over some period (very recently ended) can be gathered and published. * @param time Time; the time to be used in the notification (usually the current time) */ public void notifyTime(Time time) { if (time.gt(this.updateTime)) { try { sendStatisticsUpdate(); } catch (IMBException exception) { throw new RuntimeException("Cannot send statistics update.", exception); } } } /** * @throws IMBException when the transmission of the IMB message fails */ public void sendStatisticsUpdate() throws IMBException { List> groups = this.query.getTrajectoryGroups(this.updateTime); Length tdist = this.totalTravelDistance.getValue(this.query, this.updateTime, groups); Duration ttt = this.totalTravelTime.getValue(this.query, this.updateTime, groups); Speed ms = this.meanSpeed.getValue(this.query, this.updateTime, groups); Duration mttpdist = this.meanTravelTimePerDistance.getValue(this.query, this.updateTime, groups); Length mtl = this.meanTripLength.getValue(this.query, this.updateTime, groups); Duration tdel = this.totalDelay.getValue(this.query, this.updateTime, groups); Dimensionless nos = this.totalNumberOfStops.getValue(this.query, this.updateTime, groups); double time = this.updateTime.si; System.out.println("===== @time " + time + " s on " + this.query.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); this.connector.postIMBMessage("StatisticsGTULane", IMBEventType.CHANGE, new Object[] {time, this.query.getId(), tdist.si, ttt.si, ms.si, mttpdist.si, tdel.si, mtl.si, nos.si}); this.updateTime = this.updateTime.plus(this.transmissionInterval); } }