From 11e4fde5863b1c1f7d7879f8d1e68c7d6dca4256 Mon Sep 17 00:00:00 2001 From: brutzman <brutzman@nps.edu> Date: Sat, 1 Jan 2022 22:34:09 -0800 Subject: [PATCH] Class to represent Track from list of PDUs --- examples/src/OpenDis7Examples/PduTrack.java | 320 ++++++++++++++++++++ 1 file changed, 320 insertions(+) create mode 100644 examples/src/OpenDis7Examples/PduTrack.java diff --git a/examples/src/OpenDis7Examples/PduTrack.java b/examples/src/OpenDis7Examples/PduTrack.java new file mode 100644 index 0000000000..f96abb1aff --- /dev/null +++ b/examples/src/OpenDis7Examples/PduTrack.java @@ -0,0 +1,320 @@ +/* +Copyright (c) 1995-2021 held by the author(s). All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + * Neither the names of the Naval Postgraduate School (NPS) + Modeling Virtual Environments and Simulation (MOVES) Institute + https://www.nps.edu and https://www.nps.edu/web/moves + nor the names of its contributors may be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ +// TODO move into open-dis7 distribution tree in package edu.nps.moves.dis7.utilities.stream; + +package OpenDis7Examples; + +import edu.nps.moves.dis7.enumerations.DisPduType; +import edu.nps.moves.dis7.pdus.EntityStatePdu; +import edu.nps.moves.dis7.pdus.EulerAngles; +import edu.nps.moves.dis7.pdus.Pdu; +import edu.nps.moves.dis7.pdus.Vector3Double; +import java.util.ArrayList; + +/** + * Create a track from DIS ESPDUs + * @author brutzman + */ +public class PduTrack { + + private ArrayList<Pdu> pduList = new ArrayList<>(); + + private ArrayList<Vector3Double> waypointsList = new ArrayList<>(); + private ArrayList<EulerAngles> anglesList = new ArrayList<>(); + private ArrayList<Integer> timestampList = new ArrayList<>(); + + private String descriptor = new String(); + private String x3dTimeSensorDEF = new String(); + private String x3dPositionInterpolatorDEF = new String(); + private String x3dOrientationInterpolatorDEF = new String(); + + private String TRACE_PREFIX = "[" + (PduTrack.class.getSimpleName()) + "] "; + + /** + * Constructor design goal: additional built-in initialization conveniences can go here + */ + public PduTrack() + { + // Potential constructor is under consideration. Constructor is not currently needed. + } + + /** + * Get simple descriptor (such as parent class name) for this SimulationManager, used in trace statements + * @return simple descriptor name + */ + public String getDescriptor() + { + return descriptor; + } + /** + * Set new simple descriptor (such as parent class name) for this SimulationManager, used in trace statements + * @param newDescriptor simple descriptor name for this interface + * @return same object to permit progressive setters */ + public PduTrack setDescriptor(String newDescriptor) + { + if (newDescriptor != null) + this.descriptor = newDescriptor.trim(); + TRACE_PREFIX = "[" + (PduTrack.class.getSimpleName() + " " + descriptor) + "] "; + return this; + } + + /** + * @return the waypointsList + */ + public ArrayList<Vector3Double> getWaypointsList() { + return waypointsList; + } + /** + * @return the anglesList + */ + public ArrayList<EulerAngles> getAnglesList() { + return anglesList; + } + /** + * @return the timestampList + */ + public ArrayList<Integer> getTimestampList() { + return timestampList; + } + /** + * Add PDU, typically ESPDU + * @param newPdu new Pdu to add, typically ESPDU + * @return same object to permit progressive setters + */ + public PduTrack addPdu(Pdu newPdu) + { + pduList.add(newPdu); + return this; + } + /** + * clear all PDUs + * @return same object to permit progressive setters + */ + public PduTrack clearPduLists() + { + pduList.clear(); + waypointsList.clear(); + anglesList.clear(); + timestampList.clear(); + return this; + } + + /** + * Provide DEF value if not defined by program + * @return the x3dTimeSensorDEF + */ + public String getX3dTimeSensorDEF() { + if (x3dTimeSensorDEF.isEmpty()) + x3dTimeSensorDEF = getDescriptor().replace(" ", "") + "Clock"; + return x3dTimeSensorDEF; + } + + /** + * Set DEF value for X3D node + * @param x3dTimeSensorDEF the x3dTimeSensorDEF to set + */ + public void setX3dTimeSensorDEF(String x3dTimeSensorDEF) { + this.x3dTimeSensorDEF = x3dTimeSensorDEF; + } + + /** + * Provide DEF value if not defined by program + * @return the x3dPositionInterpolatorDEF + */ + public String getX3dPositionInterpolatorDEF() { + if (x3dPositionInterpolatorDEF.isEmpty()) + x3dPositionInterpolatorDEF = getDescriptor().replace(" ", "") + "Positions"; + return x3dPositionInterpolatorDEF; + } + + /** + * Set DEF value for X3D node + * @param x3dPositionInterpolatorDEF the x3dPositionInterpolatorDEF to set + */ + public void setX3dPositionInterpolatorDEF(String x3dPositionInterpolatorDEF) { + this.x3dPositionInterpolatorDEF = x3dPositionInterpolatorDEF; + } + + /** + * Provide DEF value if not defined by program + * @return the x3dOrientationInterpolatorDEF + */ + public String getX3dOrientationInterpolatorDEF() { + if (x3dOrientationInterpolatorDEF.isEmpty()) + x3dOrientationInterpolatorDEF = getDescriptor().replace(" ", "") + "Orientations"; + return x3dOrientationInterpolatorDEF; + } + + /** + * Set DEF value for X3D node + * @param x3dOrientationInterpolatorDEF the x3dOrientationInterpolatorDEF to set + */ + public void setX3dOrientationInterpolatorDEF(String x3dOrientationInterpolatorDEF) { + this.x3dOrientationInterpolatorDEF = x3dOrientationInterpolatorDEF; + } + + /** + * Sort all points by timestamp + * @return same object to permit progressive setters + */ + public PduTrack sortPdus() + { + // TODO + // https://stackoverflow.com/questions/16252269/how-to-sort-an-arraylist + return this; + } + /** + * Compute track duration in timestamp ticks + * @return duration in timestamp ticks between initial and final ESPDU timestamps in waypointList + */ + public int getTrackDurationTicks() + { + int initialTime = -1; + int finalTime = -1; + int duration = -1; // used if pduList is empty + + for (Pdu nextPdu : pduList) + { + if (nextPdu.getPduType() == DisPduType.ENTITY_STATE) + { + if (initialTime == -1) + initialTime = nextPdu.getTimestamp(); + finalTime = nextPdu.getTimestamp(); + } + } + if ((initialTime >= 0) && (finalTime >= 0)) + duration = (finalTime - initialTime); + if (pduList.isEmpty()) + { + System.out.println(TRACE_PREFIX + "getTrackDuration() computed illegal duration=" + duration + " due to empty pdu list"); + } + else if ((duration <= 0)) + { + System.out.println(TRACE_PREFIX + "getTrackDuration() computed illegal duration=" + duration + " due to illegal pdu list"); + } + return duration; + } + /** + * Compute track duration in seconds + * @return duration in seconds between initial and final ESPDU timestamps in waypointList + */ + public float getTrackDurationSeconds() + { + float durationSeconds = getTrackDurationTicks() * 1.0f; // TODO convert + return durationSeconds; + } + /** + * Create waypoints and angles using all PDU points + * @return same object to permit progressive setters + */ + public PduTrack createRawWaypoints() + { + // https://stackoverflow.com/questions/6536094/java-arraylist-copy + + getWaypointsList().clear(); + getAnglesList().clear(); + for (Pdu nextPdu : pduList) + { + if (nextPdu.getPduType() == DisPduType.ENTITY_STATE) + { + EntityStatePdu espdu = (EntityStatePdu)nextPdu; + getWaypointsList().add(espdu.getEntityLocation()); + getAnglesList().add(espdu.getEntityOrientation()); + getTimestampList().add(espdu.getTimestamp()); + } + } + return this; + } + /** + * Create TimeSensor from Pdu list + * @return X3D TimeSensor as string + */ + public String createX3dTimeSensorString() + { + StringBuilder sb = new StringBuilder(); + sb.append("<TimeSensor"); + sb.append(" DEF='").append(getX3dTimeSensorDEF()).append("'"); + sb.append(" cycleInterval='").append(String.valueOf(getTrackDurationSeconds())).append("'"); + sb.append(" loop='true'"); + sb.append("/>"); + + return sb.toString(); + } + /** + * Create TimeSensor from Pdu list + * @return X3D TimeSensor as string + */ + public String createX3dPositionInterpolatorString() + { + StringBuilder sb = new StringBuilder(); + sb.append("<PositionInterpolator"); + sb.append(" DEF='").append(getX3dPositionInterpolatorDEF()).append("'"); + sb.append(" key='"); + for (int i = 0; i < timestampList.size(); i++) + { + float nextDuration = timestampList.get(i) * 1.0f; // TODO convert + sb.append(String.valueOf(nextDuration)); + if (i < timestampList.size() - 1) + sb.append(" "); + } + sb.append("'"); + sb.append("/>"); + + return sb.toString(); + } + + /** Self test to check basic operation, invoked by main() */ + public void selfTest() + { + // TODO + } + + /** + * Main method for testing. + * @see <a href="https://docs.oracle.com/javase/tutorial/getStarted/application/index.html">Java Tutorials: A Closer Look at the "Hello World!" Application</a> + * @param args [address, port, descriptor] command-line arguments are an array of optional String parameters that are passed from execution environment during invocation + */ + public static void main(String[] args) + { + System.out.println("*** PduTrack main() self test started..."); + + PduTrack pduTrack = new PduTrack(); + + pduTrack.setDescriptor("main() self test"); + + pduTrack.selfTest(); + + System.out.println("*** PduTrack main() self test complete."); + } +} -- GitLab