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