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