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