View Javadoc
1   package org.opentrafficsim.sim0mq.kpi;
2   
3   import java.io.Serializable;
4   
5   import org.djunits.unit.SpeedUnit;
6   import org.djunits.value.vdouble.scalar.Speed;
7   import org.djunits.value.vdouble.scalar.Time;
8   import org.opentrafficsim.kpi.sampling.indicator.MeanSpeed;
9   import org.opentrafficsim.kpi.sampling.indicator.MeanTravelTimePerDistance;
10  import org.opentrafficsim.kpi.sampling.indicator.MeanTripLength;
11  import org.opentrafficsim.kpi.sampling.indicator.TotalDelay;
12  import org.opentrafficsim.kpi.sampling.indicator.TotalNumberOfStops;
13  import org.opentrafficsim.kpi.sampling.indicator.TotalTravelDistance;
14  import org.opentrafficsim.kpi.sampling.indicator.TotalTravelTime;
15  
16  @SuppressWarnings("checkstyle:JavadocStyle")
17  /**
18   * OTS can publish messages about statistics or Key Performance Indicators (KPIs) of the relation between GTUs and a part of the
19   * network. Examples are average speeds, travel times, trip durations, and number of stops. The statistics can be transmitted
20   * via IMB at certain intervals. The statistics are based on the classes in the ots.road.sampling package. Most statistics
21   * consider a time interval (can be unbound) and a region in space (a collection of lanes; can be the entire network), filtered
22   * on metadata such as GTU type, origin, destination, or route.<br>
23   * When a statistic is published for the first time, a NEW message is sent to IMB to identify the type of statistic, the time
24   * interval and the lane(s) for which the statistic is calculated, and the metadata used to filter the GTUs. The CHANGE message
25   * is posted whenever an updated statistic is available, or when the sample frequency time is reached. When a statistic is no
26   * longer published, a DELETE event is posted. The Graph NEW messages are posted after the Network NEW, Node NEW, Link NEW, and
27   * Lane NEW messages are posted, as it has to be able to identify Lanes.
28   * <p>
29   * <style>table,th,td {border:1px solid grey; border-style:solid; text-align:left; border-collapse: collapse;}</style>
30   * <h2>NEW</h2>
31   * <table style="width:800px;"><caption>&nbsp;</caption>
32   * <thead>
33   * <tr>
34   * <th style="width:25%;">Variable</th>
35   * <th style="width:15%;">Type</th>
36   * <th style="width:60%;">Comments</th>
37   * </tr>
38   * </thead><tbody>
39   * <tr>
40   * <td>timestamp</td>
41   * <td>double</td>
42   * <td>time of the event, in simulation time seconds</td>
43   * </tr>
44   * <tr>
45   * <td>statisticId</td>
46   * <td>String</td>
47   * <td>a unique id for the statistic, e.g. a UUID string</td>
48   * </tr>
49   * <tr>
50   * <td>description</td>
51   * <td>String</td>
52   * <td>textual description of the statistic</td>
53   * </tr>
54   * <tr>
55   * <td>networkId</td>
56   * <td>String</td>
57   * <td>id of the Network for which the statistic is made</td>
58   * </tr>
59   * <tr>
60   * <td>numberMetadataEntries</td>
61   * <td>int</td>
62   * <td>number of metadata entries</td>
63   * </tr>
64   * <tr>
65   * <td>metadataId_1</td>
66   * <td>String</td>
67   * <td>id of the first metadata entry</td>
68   * </tr>
69   * <tr>
70   * <td>metadataType_1</td>
71   * <td>String</td>
72   * <td>type of metadata, one of GTUTYPE, ORIGIN, DESTINATION, ROUTE</td>
73   * </tr>
74   * <tr>
75   * <td>metadataValue_1</td>
76   * <td>String</td>
77   * <td>value of the first metadata entry</td>
78   * </tr>
79   * <tr>
80   * <td>...</td>
81   * <td>&nbsp;</td>
82   * <td>&nbsp;</td>
83   * </tr>
84   * <tr>
85   * <td>metadataId_n</td>
86   * <td>String</td>
87   * <td>id of the last metadata entry</td>
88   * </tr>
89   * <tr>
90   * <td>metadataType_n</td>
91   * <td>String</td>
92   * <td>type of metadata, one of GTUTYPE, ORIGIN, DESTINATION, ROUTE</td>
93   * </tr>
94   * <tr>
95   * <td>metadataValue_n</td>
96   * <td>String</td>
97   * <td>value of the last metadata entry</td>
98   * </tr>
99   * <td>numberSpaceTimeRegions</td>
100  * <td>int</td>
101  * <td>number of space-time regions for this statistic</td>
102  * </tr>
103  * <tr>
104  * <td>startTime_1</td>
105  * <td>double</td>
106  * <td>start time for the first space time region, in seconds</td>
107  * </tr>
108  * <tr>
109  * <td>endTime_1</td>
110  * <td>double</td>
111  * <td>end time for the first space time region, in seconds</td>
112  * </tr>
113  * <tr>
114  * <td>linkId_1</td>
115  * <td>String</td>
116  * <td>id of the first Link for the space-time region</td>
117  * </tr>
118  * <tr>
119  * <td>laneId_1</td>
120  * <td>String</td>
121  * <td>id of the first Lane in the link for the space-time region</td>
122  * </tr>
123  * <tr>
124  * <td>...</td>
125  * <td>&nbsp;</td>
126  * <td>&nbsp;</td>
127  * </tr>
128  * <tr>
129  * <td>startTime_n</td>
130  * <td>double</td>
131  * <td>start time for the last space time region, in seconds</td>
132  * </tr>
133  * <tr>
134  * <td>endTime_n</td>
135  * <td>double</td>
136  * <td>end time for the last space time region, in seconds</td>
137  * </tr>
138  * <tr>
139  * <td>linkId_n</td>
140  * <td>String</td>
141  * <td>id of the last Link for the space-time region</td>
142  * </tr>
143  * <tr>
144  * <td>laneId_n</td>
145  * <td>String</td>
146  * <td>id of the last Lane in the link for the space-time region</td>
147  * </tr>
148  * <tr>
149  * <td>connected</td>
150  * <td>boolean</td>
151  * <td>whether the lanes in the space-time regions are longitudinally connected or not</td>
152  * </tr>
153  * <tr>
154  * <td>transmissionInterval</td>
155  * <td>double</td>
156  * <td>transmission interval of the statistic in seconds</td>
157  * </tr>
158  * </tbody>
159  * </table>
160  * </p>
161  * <p>
162  * <h2>CHANGE</h2>
163  * <table style="width:800px;"><caption>&nbsp;</caption>
164  * <thead>
165  * <tr>
166  * <th style="width:25%;">Variable</th>
167  * <th style="width:15%;">Type</th>
168  * <th style="width:60%;">Comments</th>
169  * </tr>
170  * </thead><tbody>
171  * <tr>
172  * <td>timestamp</td>
173  * <td>double</td>
174  * <td>time of the event, in simulation time seconds</td>
175  * </tr>
176  * <tr>
177  * <td>statisticId</td>
178  * <td>String</td>
179  * <td>the unique id for the statistic, e.g. a UUID string</td>
180  * </tr>
181  * <tr>
182  * <td>totalGtuDistance</td>
183  * <td>double</td>
184  * <td>total distance traveled by filtered GTUs in the given time and space, in meters</td>
185  * </tr>
186  * <tr>
187  * <td>totalGtuTravelTime</td>
188  * <td>double</td>
189  * <td>total travel time by filtered GTUs in the given time and space, in seconds</td>
190  * </tr>
191  * <tr>
192  * <td>averageGtuSpeed</td>
193  * <td>double</td>
194  * <td>average filtered GTU speed in the given time and space, in meter/second</td>
195  * </tr>
196  * <tr>
197  * <td>averageGtuTravelTimePerKm</td>
198  * <td>double</td>
199  * <td>average filtered GTU travel time in the given time and space, in seconds per km</td>
200  * </tr>
201  * <tr>
202  * <td>totalGtuTimeDelay</td>
203  * <td>double</td>
204  * <td>total time delay incurred by the filtered GTUs in the given time and space, in seconds</td>
205  * </tr>
206  * <tr>
207  * <td>averageTripLength</td>
208  * <td>double</td>
209  * <td>average length of the trip of the filtered GTUs in the given time and space, in seconds</td>
210  * </tr>
211  * <tr>
212  * <td>totalNumberStops</td>
213  * <td>double</td>
214  * <td>total number of stops that GTUs made in the given time and space, dimensionless</td>
215  * </tr>
216  * </tbody>
217  * </table>
218  * </p>
219  * <p>
220  * <h2>DELETE</h2>
221  * <table style="width:800px;"><caption>&nbsp;</caption>
222  * <thead>
223  * <tr>
224  * <th style="width:25%;">Variable</th>
225  * <th style="width:15%;">Type</th>
226  * <th style="width:60%;">Comments</th>
227  * </tr>
228  * </thead><tbody>
229  * <tr>
230  * <td>timestamp</td>
231  * <td>double</td>
232  * <td>time of the event, in simulation time seconds</td>
233  * </tr>
234  * <tr>
235  * <td>statisticId</td>
236  * <td>String</td>
237  * <td>the unique id for the statistic that is removed</td>
238  * </tr>
239  * </tbody>
240  * </table>
241  * </p>
242  * <p>
243  * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
244  * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
245  * <p>
246  * @version $Revision$, $LastChangedDate$, by $Author$, initial version Sep 16, 2016 <br>
247  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
248  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
249  */
250 public class Sim0MQKpiTransceiver implements Serializable
251 {
252 
253     /** */
254     private static final long serialVersionUID = 20160923L;
255 
256     /** IMB connector. */
257     // private final Connector connector;
258 
259     /** The query for the statistic. */
260     // private final Query query;
261 
262     /** The Network id for which the graph is made. */
263     // private final String networkId;
264 
265     /** The interval between generation of graphs. */
266     // private final Duration transmissionInterval;
267 
268     private TotalTravelDistance totalTravelDistance = new TotalTravelDistance();
269 
270     private TotalTravelTime totalTravelTime = new TotalTravelTime();
271 
272     private MeanSpeed meanSpeed = new MeanSpeed(this.totalTravelDistance, this.totalTravelTime);
273 
274     private MeanTravelTimePerDistance meanTravelTimePerKm = new MeanTravelTimePerDistance(this.meanSpeed);
275 
276     private MeanTripLength meanTripLength = new MeanTripLength();
277 
278     private TotalDelay totalDelay = new TotalDelay(new Speed(130.0, SpeedUnit.KM_PER_HOUR));
279 
280     private TotalNumberOfStops totalNumberOfStops = new TotalNumberOfStops();
281 
282     private Time updateTime = Time.ZERO;
283 
284     // TODO implement DELETE message
285 
286     // /**
287     // * Construct a new ImbKpiTransceiver.
288     // * @param connector Connector; the IMB connector
289     // * @param time Time; time of creation
290     // * @param networkId String; the network id
291     // * @param query Query; the statistics query
292     // * @param transmissionInterval Duration; the interval between generation of graphs
293     // * @throws IMBException when the post of the IMB message fails
294     // */
295     // public Sim0MQKpiTransceiver(final Connector connector, Time time, String networkId, final Query query,
296     // final Duration transmissionInterval) throws IMBException
297     // {
298     // this.connector = connector;
299     // this.query = query;
300     // this.networkId = networkId;
301     // this.transmissionInterval = transmissionInterval;
302     //
303     // List<Object> newMessage = new ArrayList<>();
304     // newMessage.add(time.si);
305     // newMessage.add(query.getId());
306     // newMessage.add(query.toString());
307     // newMessage.add(this.networkId);
308     // newMessage.add((int) 0); // TODO numberMetadataEntries
309     // newMessage.add((int) 0); // TODO numberSpaceTimeRegions
310     // newMessage.add(false); // TODO "connected" not part of query anymore
311     // newMessage.add(true); // TODO totalTrajectory
312     // newMessage.add(transmissionInterval.si);
313     //
314     // this.connector.postIMBMessage("StatisticsGTULane", IMBEventType.NEW, newMessage.toArray());
315     // sendStatisticsUpdate();
316     // }
317     //
318     // /**
319     // * Notifies about time, such that statistics over some period (very recently ended) can be gathered and published.
320     // * @param time the time to be used in the notification (usually the current time)
321     // */
322     // public void notifyTime(Time time)
323     // {
324     // if (time.gt(this.updateTime))
325     // {
326     // try
327     // {
328     // sendStatisticsUpdate();
329     // }
330     // catch (IMBException exception)
331     // {
332     // throw new RuntimeException("Cannot send statistics update.", exception);
333     // }
334     // }
335     // }
336     //
337     // /**
338     // * @throws IMBException when the transmission of the IMB message fails
339     // */
340     // public void sendStatisticsUpdate() throws IMBException
341     // {
342     // Length tdist = this.totalTravelDistance.getValue(this.query, this.updateTime);
343     // Duration ttt = this.totalTravelTime.getValue(this.query, this.updateTime);
344     // Speed ms = this.meanSpeed.getValue(this.query, this.updateTime);
345     // Duration mttpkm = this.meanTravelTimePerKm.getValue(this.query, this.updateTime);
346     // Length mtl = this.meanTripLength.getValue(this.query, this.updateTime);
347     // Duration tdel = this.totalDelay.getValue(this.query, this.updateTime);
348     // Dimensionless nos = this.totalNumberOfStops.getValue(this.query, this.updateTime);
349     // double time = this.updateTime.si;
350     // System.out.println("===== @time " + time + " s =====");
351     // System.out.println("Total distance " + tdist);
352     // System.out.println("Total travel time " + ttt);
353     // System.out.println("Mean speed " + ms);
354     // System.out.println("Mean travel time " + mttpkm + " (per km)");
355     // System.out.println("Mean trip length " + mtl);
356     // System.out.println("Total delay " + tdel);
357     // System.out.println("Number of stops " + nos);
358     // this.connector.postIMBMessage("StatisticsGTULane", IMBEventType.CHANGE,
359     // new Object[] { time, this.query.getId(), tdist.si, ttt.si, ms.si, mttpkm.si, tdel.si, mtl.si, nos.si });
360     // this.updateTime = this.updateTime.plus(this.transmissionInterval);
361     // }
362 
363 }