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 }