1 package org.opentrafficsim.sim0mq.kpi; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import org.djunits.value.vdouble.scalar.Time; 7 import org.opentrafficsim.kpi.sampling.KpiLaneDirection; 8 import org.opentrafficsim.kpi.sampling.Sampler; 9 10 /** 11 * XXX ABSTRACT TEMPORARILY 12 * <p> 13 * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br> 14 * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>. 15 * <p> 16 * @version $Revision$, $LastChangedDate$, by $Author$, initial version 12 okt. 2016 <br> 17 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a> 18 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a> 19 * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a> 20 */ 21 public abstract class Sim0MQSampler extends Sampler 22 { 23 /** The IMBConnector. */ 24 // private final IMBConnector imbConnector; 25 26 /** Transceiver of statistics. */ 27 private Sim0MQKpiTransceiver sim0mqKpiTransceiver; 28 29 /** The last received timestamp. */ 30 private Time lastTimestamp = Time.ZERO; 31 32 /** The recording start times per KpiLaneDirection. */ 33 private final Map<KpiLaneDirection, Time> startRecordingMap = new HashMap<>(); 34 35 /** The recording stop times per KpiLaneDirection. */ 36 private final Map<KpiLaneDirection, Time> stopRecordingMap = new HashMap<>(); 37 38 /** the nodes. */ 39 protected final Map<String, NodeData> nodes = new HashMap<>(); 40 41 /** the links. */ 42 protected final Map<String, LinkData> links = new HashMap<>(); 43 44 /** the lanes. */ 45 protected final Map<String, LaneData> lanes = new HashMap<>(); 46 47 /** the gtus. */ 48 protected final Map<String, GtuData> gtus = new HashMap<>(); 49 50 /** last lane of gtus. */ 51 protected final Map<String, KpiLaneDirection> lastLanes = new HashMap<>(); 52 53 /** the default gtu type (for now). */ 54 // protected final GtuTypeData defaultGtuType; 55 56 /** the default route (for now). */ 57 // protected final RouteData defaultRoute; 58 59 // /** 60 // * Main program for IMBSampler. Listens to events on the IMB bus and calculates and publishes statistics. 61 // * @param args the arguments with [0]=IP address, [1]=port 62 // * @throws IMBException in case of invalid arguments 63 // */ 64 // public static void main(final String[] args) throws IMBException 65 // { 66 // if (args.length == 0) 67 // { 68 // new Sim0MQSampler(new IMBConnector("localhost", 4000, "OTS_IMB_KPI", 1, "OTS_RT")); 69 // } 70 // else 71 // { 72 // if (args.length != 5) 73 // { 74 // throw new IMBException("Use as follows: java -jar IMBSampler host port model modelId federation"); 75 // } 76 // String host = args[0]; 77 // int port = Integer.valueOf(args[1]); 78 // String modelName = args[2]; 79 // int modelId = Integer.valueOf(args[3]); 80 // String federation = args[4]; 81 // new Sim0MQSampler(new IMBConnector(host, port, modelName, modelId, federation)); 82 // } 83 // } 84 // 85 // /** 86 // * Constructor with listeners for nodes, links, lanes and gtu's. 87 // * @param imbConnector IMB connection 88 // * @throws IMBException on connection error 89 // */ 90 // public Sim0MQSampler(IMBConnector imbConnector) throws IMBException 91 // { 92 // this.imbConnector = imbConnector; 93 // 94 // // default GTU Type and default route 95 // this.defaultGtuType = new GtuTypeData("car"); 96 // NodeData nodeA = new NodeData("NodeA", new CartesianPoint(0, 0, 0)); 97 // NodeData nodeB = new NodeData("NodeB", new CartesianPoint(1, 1, 0)); 98 // this.nodes.put(nodeA.getNodeName(), nodeA); 99 // this.nodes.put(nodeB.getNodeName(), nodeB); 100 // this.defaultRoute = new RouteData("Route A-B", nodeA, nodeB); 101 // 102 // Transceiver nodeTransceiver = new NodeTransceiver(this, this.imbConnector); 103 // this.imbConnector.register(nodeTransceiver.getId(), nodeTransceiver); 104 // 105 // Transceiver linkTransceiver = new LinkTransceiver(this, this.imbConnector); 106 // this.imbConnector.register(linkTransceiver.getId(), linkTransceiver); 107 // 108 // Transceiver laneTransceiver = new LaneTransceiver(this, this.imbConnector); 109 // this.imbConnector.register(laneTransceiver.getId(), laneTransceiver); 110 // 111 // Transceiver gtuTransceiver = new GTUTransceiver(this, this.imbConnector); 112 // this.imbConnector.register(gtuTransceiver.getId(), gtuTransceiver); 113 // } 114 // 115 // /** {@inheritDoc} */ 116 // @Override 117 // public final Time now() 118 // { 119 // return this.lastTimestamp; 120 // } 121 // 122 // /** {@inheritDoc} */ 123 // @Override 124 // public final void scheduleStartRecording(final Time time, final KpiLaneDirection kpiLaneDirection) 125 // { 126 // // store the start time in the internal map to indicate from which time we want to consider events. 127 // this.startRecordingMap.put(kpiLaneDirection, time); 128 // } 129 // 130 // /** {@inheritDoc} */ 131 // @Override 132 // public final void scheduleStopRecording(final Time time, final KpiLaneDirection kpiLaneDirection) 133 // { 134 // // store the stop time in the internal map to indicate from which time we want to consider events. 135 // this.stopRecordingMap.put(kpiLaneDirection, time); 136 // } 137 // 138 // /** {@inheritDoc} */ 139 // @Override 140 // public final void initRecording(final KpiLaneDirection kpiLaneDirection) 141 // { 142 // // Nothing to do -- we get data on all GTUs 143 // } 144 // 145 // /** {@inheritDoc} */ 146 // @Override 147 // public final void finalizeRecording(final KpiLaneDirection kpiLaneDirection) 148 // { 149 // // Nothing to do -- we get data on all GTUs 150 // } 151 // 152 // /** 153 // * Sample the data received from a GTU. 154 // * @param timeStamp time of the sampling 155 // * @param gtuId gtu 156 // * @param laneId lane 157 // * @param forward driving direction 158 // * @param longitudinalPosition position 159 // * @param speed speed 160 // * @param acceleration acceleration 161 // */ 162 // protected void sample(double timeStamp, String gtuId, String laneId, boolean forward, double longitudinalPosition, 163 // double speed, double acceleration) 164 // { 165 // // update clock 166 // updateClock(timeStamp); 167 // if (!this.lanes.containsKey(laneId) || !this.gtus.containsKey(gtuId)) 168 // { 169 // // lane not part of this network, or new message of gtu not (yet) received 170 // return; 171 // } 172 // KpiLaneDirection kpiLaneDirection = new KpiLaneDirection(this.lanes.get(laneId), 173 // forward ? KpiGtuDirectionality.DIR_PLUS : KpiGtuDirectionality.DIR_MINUS); 174 // GtuData gtu = this.gtus.get(gtuId); 175 // if (this.lastLanes.containsKey(gtuId) && contains(this.lastLanes.get(gtuId)) 176 // && !this.lastLanes.get(gtuId).equals(kpiLaneDirection)) 177 // { 178 // processGtuRemoveEvent(this.lastLanes.get(gtuId), gtu); 179 // } 180 // if ((!this.lastLanes.containsKey(gtuId) || !this.lastLanes.get(gtuId).equals(kpiLaneDirection)) 181 // && contains(kpiLaneDirection)) 182 // { 183 // processGtuAddEvent(kpiLaneDirection, new Length(longitudinalPosition, LengthUnit.SI), 184 // new Speed(speed, SpeedUnit.SI), new Acceleration(acceleration, AccelerationUnit.SI), now(), gtu); 185 // } 186 // else if (contains(kpiLaneDirection)) 187 // { 188 // // TEST LOOP 189 // for (Trajectory trajectory : getTrajectoryGroup(kpiLaneDirection).getTrajectories()) 190 // { 191 // if (trajectory.getGtuId().equals(gtu.getId())) 192 // { 193 // float[] x = trajectory.getX(); 194 // float pos = (float) (kpiLaneDirection.getKpiDirection().isPlus() ? longitudinalPosition 195 // : kpiLaneDirection.getLaneData().getLength().si - longitudinalPosition); 196 // if (pos < x[x.length - 1]) 197 // { 198 // System.err.println("Vehicle " + gtu.getId() + " is moving backwards on lane " 199 // + kpiLaneDirection.getLaneData() + " or direction on lane is incorrect."); 200 // } 201 // break; 202 // } 203 // } 204 // // END TEST LOOP 205 // // move on current 206 // processGtuMoveEvent(kpiLaneDirection, new Length(longitudinalPosition, LengthUnit.SI), 207 // new Speed(speed, SpeedUnit.SI), new Acceleration(acceleration, AccelerationUnit.SI), now(), gtu); 208 // } 209 // this.lastLanes.put(gtuId, kpiLaneDirection); 210 // } 211 // 212 // /** 213 // * @param imbKpiTransceiver set imbKpiTransceiver. 214 // */ 215 // public void setImbKpiTransceiver(Sim0MQKpiTransceiver imbKpiTransceiver) 216 // { 217 // this.imbKpiTransceiver = imbKpiTransceiver; 218 // } 219 // 220 // /** 221 // * Updates clock and triggers timed events. 222 // * @param timeStamp most recent time stamp 223 // */ 224 // protected void updateClock(double timeStamp) 225 // { 226 // if (this.lastTimestamp.si >= timeStamp && this.lastTimestamp.si > 0) 227 // { 228 // return; 229 // } 230 // if (this.imbKpiTransceiver != null) 231 // { 232 // this.imbKpiTransceiver.notifyTime(now()); 233 // } 234 // this.lastTimestamp = new Time(timeStamp, TimeUnit.SI); 235 // Iterator<KpiLaneDirection> iterator = this.startRecordingMap.keySet().iterator(); 236 // while (iterator.hasNext()) 237 // { 238 // KpiLaneDirection kpiLaneDirection = iterator.next(); 239 // if (now().ge(this.startRecordingMap.get(kpiLaneDirection))) 240 // { 241 // startRecording(kpiLaneDirection); 242 // iterator.remove(); 243 // } 244 // } 245 // iterator = this.stopRecordingMap.keySet().iterator(); 246 // while (iterator.hasNext()) 247 // { 248 // KpiLaneDirection kpiLaneDirection = iterator.next(); 249 // if (now().ge(this.stopRecordingMap.get(kpiLaneDirection))) 250 // { 251 // stopRecording(kpiLaneDirection); 252 // iterator.remove(); 253 // } 254 // } 255 // } 256 // 257 // /* ************************************************************************************************************** */ 258 // /* ********************************************** GTU LISTENER ************************************************** */ 259 // /* ************************************************************************************************************** */ 260 // 261 // /** the IMB GTU listener. */ 262 // private static class GTUTransceiver implements Transceiver 263 // { 264 // /** the sampler. */ 265 // private final Sim0MQSampler sampler; 266 // 267 // /** The IMBConnector. */ 268 // private final IMBConnector imbConnector; 269 // 270 // /** 271 // * @param sampler the sampler 272 // * @param imbConnector the connector 273 // */ 274 // public GTUTransceiver(final Sim0MQSampler sampler, final IMBConnector imbConnector) 275 // { 276 // this.imbConnector = imbConnector; 277 // this.sampler = sampler; 278 // } 279 // 280 // /** {@inheritDoc} */ 281 // @Override 282 // @SuppressWarnings("unused") 283 // public void handleMessageFromIMB(String imbEventName, TByteBuffer imbPayload) throws IMBException 284 // { 285 // int imbEventTypeNr = imbPayload.readInt32(); 286 // switch (imbEventTypeNr) 287 // { 288 // case TEventEntry.ACTION_NEW: 289 // { 290 // double timeStamp = imbPayload.readDouble(); 291 // String gtuId = imbPayload.readString(); 292 // double x = imbPayload.readDouble(); 293 // double y = imbPayload.readDouble(); 294 // double z = imbPayload.readDouble(); 295 // double rotZ = imbPayload.readDouble(); 296 // String networkId = imbPayload.readString(); 297 // String linkId = imbPayload.readString(); 298 // // TODO laneId should be unique on its own 299 // String laneId = linkId + "." + imbPayload.readString(); 300 // double longitudinalPosition = imbPayload.readDouble(); 301 // double length = imbPayload.readDouble(); 302 // double width = imbPayload.readDouble(); 303 // byte r = imbPayload.readByte(); 304 // byte g = imbPayload.readByte(); 305 // byte b = imbPayload.readByte(); 306 // 307 // // TODO GTU Type and Route should be part of the NEW message 308 // GtuData gtuData = new GtuData(gtuId, this.sampler.defaultGtuType, this.sampler.defaultRoute); 309 // this.sampler.gtus.put(gtuId, gtuData); 310 // break; 311 // } 312 // 313 // case TEventEntry.ACTION_CHANGE: 314 // { 315 // double timeStamp = imbPayload.readDouble(); 316 // String gtuId = imbPayload.readString(); 317 // double x = imbPayload.readDouble(); 318 // double y = imbPayload.readDouble(); 319 // double z = imbPayload.readDouble(); 320 // double rotZ = imbPayload.readDouble(); 321 // String networkId = imbPayload.readString(); 322 // String linkId = imbPayload.readString(); 323 // // TODO laneId should be unique on its own 324 // String laneId = linkId + "." + imbPayload.readString(); 325 // double longitudinalPosition = imbPayload.readDouble(); 326 // double speed = imbPayload.readDouble(); 327 // double acceleration = imbPayload.readDouble(); 328 // String turnIndicatorStatus = imbPayload.readString(); 329 // boolean brakingLights = imbPayload.readBoolean(); 330 // double odometer = imbPayload.readDouble(); 331 // boolean forward = true; 332 // 333 // this.sampler.sample(timeStamp, gtuId, laneId, forward, longitudinalPosition, speed, acceleration); 334 // 335 // break; 336 // } 337 // 338 // case TEventEntry.ACTION_DELETE: 339 // { 340 // // ignore for now. 341 // break; 342 // } 343 // 344 // default: 345 // break; 346 // } 347 // } 348 // 349 // @Override 350 // public String getId() 351 // { 352 // return "GTU"; 353 // } 354 // 355 // @Override 356 // public Connector getConnector() 357 // { 358 // return this.imbConnector; 359 // } 360 // } 361 // 362 // /* ************************************************************************************************************** */ 363 // /* ********************************************* NODE LISTENER ************************************************** */ 364 // /* ************************************************************************************************************** */ 365 // 366 // /** the IMB Node listener. */ 367 // private static class NodeTransceiver implements Transceiver 368 // { 369 // /** the sampler. */ 370 // private final Sim0MQSampler sampler; 371 // 372 // /** The IMBConnector. */ 373 // private final IMBConnector imbConnector; 374 // 375 // /** 376 // * @param sampler the sampler 377 // * @param imbConnector the connector 378 // */ 379 // public NodeTransceiver(final Sim0MQSampler sampler, final IMBConnector imbConnector) 380 // { 381 // this.imbConnector = imbConnector; 382 // this.sampler = sampler; 383 // } 384 // 385 // /** {@inheritDoc} */ 386 // @Override 387 // @SuppressWarnings("unused") 388 // public void handleMessageFromIMB(String imbEventName, TByteBuffer imbPayload) throws IMBException 389 // { 390 // int imbEventTypeNr = imbPayload.readInt32(); 391 // switch (imbEventTypeNr) 392 // { 393 // case TEventEntry.ACTION_NEW: 394 // { 395 // double timeStamp = imbPayload.readDouble(); 396 // String networkId = imbPayload.readString(); 397 // String nodeId = imbPayload.readString(); 398 // System.out.println("Node " + nodeId + " received."); 399 // double x = imbPayload.readDouble(); 400 // double y = imbPayload.readDouble(); 401 // double z = imbPayload.readDouble(); 402 // CartesianPoint p = new CartesianPoint(x, y, z); 403 // NodeData nodeData = new NodeData(nodeId, p); 404 // this.sampler.nodes.put(nodeId, nodeData); 405 // break; 406 // } 407 // 408 // case TEventEntry.ACTION_CHANGE: 409 // { 410 // // ignore for now. 411 // break; 412 // } 413 // 414 // case TEventEntry.ACTION_DELETE: 415 // { 416 // // ignore for now. 417 // break; 418 // } 419 // 420 // default: 421 // break; 422 // } 423 // } 424 // 425 // @Override 426 // public String getId() 427 // { 428 // return "Node"; 429 // } 430 // 431 // @Override 432 // public Connector getConnector() 433 // { 434 // return this.imbConnector; 435 // } 436 // } 437 // 438 // /* ************************************************************************************************************** */ 439 // /* ********************************************* LINK LISTENER ************************************************** */ 440 // /* ************************************************************************************************************** */ 441 // 442 // /** the IMB Link listener. */ 443 // private static class LinkTransceiver implements Transceiver 444 // { 445 // /** the sampler. */ 446 // private final Sim0MQSampler sampler; 447 // 448 // /** The IMBConnector. */ 449 // private final IMBConnector imbConnector; 450 // 451 // /** 452 // * @param sampler the sampler 453 // * @param imbConnector the connector 454 // */ 455 // public LinkTransceiver(final Sim0MQSampler sampler, final IMBConnector imbConnector) 456 // { 457 // this.imbConnector = imbConnector; 458 // this.sampler = sampler; 459 // } 460 // 461 // /** {@inheritDoc} */ 462 // @Override 463 // @SuppressWarnings("unused") 464 // public void handleMessageFromIMB(String imbEventName, TByteBuffer imbPayload) throws IMBException 465 // { 466 // int imbEventTypeNr = imbPayload.readInt32(); 467 // switch (imbEventTypeNr) 468 // { 469 // case TEventEntry.ACTION_NEW: 470 // { 471 // double timeStamp = imbPayload.readDouble(); 472 // String networkId = imbPayload.readString(); 473 // String linkId = imbPayload.readString(); 474 // System.out.println("Link " + linkId + " received."); 475 // String startNodeId = imbPayload.readString(); 476 // String endNodeId = imbPayload.readString(); 477 // int dlNumPoints = imbPayload.readInt32(); 478 // double len = 0.0; 479 // double x = imbPayload.readDouble(); 480 // double y = imbPayload.readDouble(); 481 // double z = imbPayload.readDouble(); 482 // CartesianPoint p1 = new CartesianPoint(x, y, z); 483 // for (int i = 1; i < dlNumPoints; i++) 484 // { 485 // x = imbPayload.readDouble(); 486 // y = imbPayload.readDouble(); 487 // z = imbPayload.readDouble(); 488 // CartesianPoint p2 = new CartesianPoint(x, y, z); 489 // len += p1.distance(p2); 490 // p1 = p2; 491 // } 492 // Length length = new Length(len, LengthUnit.SI); 493 // LinkData linkData = new LinkData(linkId, this.sampler.nodes.get(startNodeId), 494 // this.sampler.nodes.get(endNodeId), length); 495 // this.sampler.links.put(linkId, linkData); 496 // break; 497 // } 498 // 499 // case TEventEntry.ACTION_CHANGE: 500 // { 501 // // ignore for now. 502 // break; 503 // } 504 // 505 // case TEventEntry.ACTION_DELETE: 506 // { 507 // // ignore for now. 508 // break; 509 // } 510 // 511 // default: 512 // break; 513 // } 514 // } 515 // 516 // @Override 517 // public String getId() 518 // { 519 // return "Link_GTU"; 520 // } 521 // 522 // @Override 523 // public Connector getConnector() 524 // { 525 // return this.imbConnector; 526 // } 527 // } 528 // 529 // /* ************************************************************************************************************** */ 530 // /* ********************************************* LANE LISTENER ************************************************** */ 531 // /* ************************************************************************************************************** */ 532 // 533 // /** the IMB Lane listener. */ 534 // private static class LaneTransceiver implements Transceiver 535 // { 536 // /** the sampler. */ 537 // private final Sim0MQSampler sampler; 538 // 539 // /** The IMBConnector. */ 540 // private final IMBConnector imbConnector; 541 // 542 // /** 543 // * @param sampler the sampler 544 // * @param imbConnector the connector 545 // */ 546 // public LaneTransceiver(final Sim0MQSampler sampler, final IMBConnector imbConnector) 547 // { 548 // this.imbConnector = imbConnector; 549 // this.sampler = sampler; 550 // } 551 // 552 // /** {@inheritDoc} */ 553 // @Override 554 // @SuppressWarnings("unused") 555 // public void handleMessageFromIMB(String imbEventName, TByteBuffer imbPayload) throws IMBException 556 // { 557 // int imbEventTypeNr = imbPayload.readInt32(); 558 // switch (imbEventTypeNr) 559 // { 560 // case TEventEntry.ACTION_NEW: 561 // { 562 // double timeStamp = imbPayload.readDouble(); 563 // String networkId = imbPayload.readString(); 564 // String linkId = imbPayload.readString(); 565 // // TODO laneId should be unique on its own, or keep network, link and lane id separate 566 // String laneId = linkId + "." + imbPayload.readString(); 567 // System.out.println("Lane " + laneId + " received."); 568 // int laneNumber = imbPayload.readInt32(); 569 // int dlNumPoints = imbPayload.readInt32(); 570 // double len = 0.0; 571 // double x = imbPayload.readDouble(); 572 // double y = imbPayload.readDouble(); 573 // double z = imbPayload.readDouble(); 574 // CartesianPoint p1 = new CartesianPoint(x, y, z); 575 // for (int i = 1; i < dlNumPoints; i++) 576 // { 577 // x = imbPayload.readDouble(); 578 // y = imbPayload.readDouble(); 579 // z = imbPayload.readDouble(); 580 // CartesianPoint p2 = new CartesianPoint(x, y, z); 581 // len += p1.distance(p2); 582 // p1 = p2; 583 // } 584 // Length length = new Length(len, LengthUnit.SI); 585 // if (!this.sampler.links.containsKey(linkId)) 586 // { 587 // System.out.println("Link not received."); 588 // } 589 // LaneData laneData = new LaneData(this.sampler.links.get(linkId), laneId, length); 590 // if (this.sampler.lanes.containsKey(laneId)) 591 // { 592 // System.out.println("Lanes not unique."); 593 // } 594 // this.sampler.lanes.put(laneId, laneData); 595 // break; 596 // } 597 // 598 // case TEventEntry.ACTION_CHANGE: 599 // { 600 // // ignore for now. 601 // break; 602 // } 603 // 604 // case TEventEntry.ACTION_DELETE: 605 // { 606 // // ignore for now. 607 // break; 608 // } 609 // 610 // default: 611 // break; 612 // } 613 // } 614 // 615 // @Override 616 // public String getId() 617 // { 618 // return "Lane_GTU"; 619 // } 620 // 621 // @Override 622 // public Connector getConnector() 623 // { 624 // return this.imbConnector; 625 // } 626 // } 627 // 628 }