From 8727b4969857f8bffa6de95641345351a360061a Mon Sep 17 00:00:00 2001 From: brennenstuhl <tobias.brennenstuhl.gy@nps.edu> Date: Mon, 22 Jun 2020 18:14:06 -0700 Subject: [PATCH] DIS reference logs updated --- .../src/PduStreamTools/PlayerPlainText.java | 284 ++---------------- .../src/PduStreamTools/README.md | 5 + .../src/PduStreamTools/RecorderPlainText.java | 12 +- .../{Coordinates.java => X3DCoordinates.java} | 13 +- ...ators.java => X3DCreateInterpolators.java} | 198 +++++++----- ...eX3dLineSet.java => X3DCreateLineSet.java} | 14 +- ....java => X3DSlidingWindowCompression.java} | 83 +---- 7 files changed, 186 insertions(+), 423 deletions(-) create mode 100644 BrennenstuhlTobias/src/PduStreamTools/README.md rename BrennenstuhlTobias/src/PduStreamTools/{Coordinates.java => X3DCoordinates.java} (74%) rename BrennenstuhlTobias/src/PduStreamTools/{CreateX3dInterpolators.java => X3DCreateInterpolators.java} (57%) rename BrennenstuhlTobias/src/PduStreamTools/{CreateX3dLineSet.java => X3DCreateLineSet.java} (89%) rename BrennenstuhlTobias/src/PduStreamTools/{SlidingWindowCompression.java => X3DSlidingWindowCompression.java} (68%) diff --git a/BrennenstuhlTobias/src/PduStreamTools/PlayerPlainText.java b/BrennenstuhlTobias/src/PduStreamTools/PlayerPlainText.java index d831a3f..6ba5eed 100644 --- a/BrennenstuhlTobias/src/PduStreamTools/PlayerPlainText.java +++ b/BrennenstuhlTobias/src/PduStreamTools/PlayerPlainText.java @@ -1,24 +1,15 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package PduStreamTools; /** * Copyright (c) 2008-2019, MOVES Institute, Naval Postgraduate School. All * rights reserved. This work is licensed under the BSD open source license, * available at https://www.movesinstitute.org/licenses/bsd.html + * */ - import static PduStreamTools.RecorderBase64.COMMENT_MARKER; import static PduStreamTools.RecorderBase64.START_COMMENT_MARKER; import static PduStreamTools.RecorderBase64.STOP_COMMENT_MARKER; import com.google.common.primitives.Longs; -import edu.nps.moves.dis7.EntityStatePdu; -import edu.nps.moves.dis7.Pdu; -import edu.nps.moves.dis7.enumerations.DISPDUType; -import edu.nps.moves.dis7.util.PduFactory; import java.io.*; import java.net.DatagramPacket; @@ -27,14 +18,17 @@ import java.net.InetAddress; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.nio.file.Path; -import java.text.NumberFormat; import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.Locale; -import java.util.Set; -import java.util.TreeMap; import java.util.regex.Pattern; +/** + * PlayerPlainText.java created on Mar 2, 2020 MOVES Institute Naval Postgraduate + * School, Monterey, CA, USA www.nps.edu + * + * @author Mike Bailey, jmbailey@nps.edu + * @author Tobias Brennenstuhl, tobias.brennenstuhl.gy@nps.edu + */ + public class PlayerPlainText { private Path disLogDirectory; @@ -78,26 +72,13 @@ public class PlayerPlainText { Arrays.sort(fs, (f1, f2) -> { return f1.getName().compareTo(f2.getName()); }); - + dsock = new DatagramSocket(); - + // -------------------- Begin Variables for Position Interpolator - //Test external SourceCode - CreateX3dInterpolators x3dInterpolators = new CreateX3dInterpolators(); - CreateX3dLineSet x3dLineSet = new CreateX3dLineSet(); + X3DCreateInterpolators x3dInterpolators = new X3DCreateInterpolators(); + X3DCreateLineSet x3dLineSet = new X3DCreateLineSet(); byte[] globalByteBufferForX3dInterPolators = null; -// Boolean firstTimeStamp = true; -// int firstLocalTimeStamp = 0; -// -// double firstLocalX = 0; -// double firstLocalY = 0; -// double firstLocalZ = 0; -// -// LinkedHashMap<Double, Coordinates> testMap = new LinkedHashMap<>(); -// -// //Setting up a NumberFormatter for limitting the decimal count to 3 -// NumberFormat coordinateNumberFormat = NumberFormat.getInstance(new Locale("en", "US")); -// coordinateNumberFormat.setMaximumFractionDigits(3); // -------------------- End Variables for Position Interpolator for (File f : fs) { @@ -160,7 +141,7 @@ public class PlayerPlainText { int tempInt = Integer.parseInt(tempString); arr[x] = tempInt; - + } // Credit: https://stackoverflow.com/questions/1086054/how-to-convert-int-to-byte @@ -218,9 +199,6 @@ public class PlayerPlainText { //Therefore a shortBuffer is created where only every forth value is stored. //it must be done with modulo instead of testing for "0" because a "0" could be there as value and not as padding byte[] bufferShort = new byte[byteBuffer2.array().length / 4]; - - - int bufferShortCounter = 0; for (int i = 1; i < byteBuffer2.array().length; i++) { @@ -235,76 +213,12 @@ public class PlayerPlainText { } DatagramPacket packet = new DatagramPacket(bufferShort, bufferShort.length, addr, port); - + globalByteBufferForX3dInterPolators = new byte[byteBuffer2.array().length / 4]; globalByteBufferForX3dInterPolators = bufferShort.clone(); - + dsock.send(packet); - //PDU Factory -// PduFactory pduFactory = new PduFactory(); -// Pdu localPdu = null; -// -// if (arr[2] == 1) { -// -// localPdu = pduFactory.createPdu(bufferShort); -// -// // ToDO figure out how to do this! makeEntityStatePDU -// EntityStatePdu localEspdu = pduFactory.makeEntityStatePdu(); -// //Put all the data we need into the localEspdu -// ByteBuffer espduBuffer = ByteBuffer.wrap(bufferShort); -// localEspdu.unmarshal(espduBuffer); -// -// double localTimeStamp = 0; -// double localX = 0; -// double localY = 0; -// double localZ = 0; -// -// double localPhi = 0; -// double localPsi = 0; -// double localTheta = 0; -// -// //Store the first timestamp to subtract it from all others -// //Same with X,Y,Z to create a local coordiante system -// if (firstTimeStamp) { -// -// firstLocalTimeStamp = localPdu.getTimestamp(); -// localTimeStamp = localPdu.getTimestamp(); -// firstLocalX = localEspdu.getEntityLocation().getX(); -// firstLocalY = localEspdu.getEntityLocation().getY(); -// firstLocalZ = localEspdu.getEntityLocation().getZ(); -// -// firstTimeStamp = false; -// } -// -// localTimeStamp = localPdu.getTimestamp(); -// localX = localEspdu.getEntityLocation().getX(); -// localY = localEspdu.getEntityLocation().getY(); -// localZ = localEspdu.getEntityLocation().getZ(); -// localPhi = localEspdu.getEntityOrientation().getPhi(); -// localPsi = localEspdu.getEntityOrientation().getPsi(); -// localTheta = localEspdu.getEntityOrientation().getTheta(); -// -// localTimeStamp = localTimeStamp - firstLocalTimeStamp; -// localX = localX - firstLocalX; -// localY = localY - firstLocalY; -// localZ = localZ - firstLocalZ; -// -// //Divide TimeStamp by 1,300,000 to get something close to a second per Unit. -// //According to the DIS standard one tick is 3600/(2^31) seconds ~ 1.6764 µs -// //1,300,000 was derived from a stream that is 61 seconds long. The number was adjusted to get a timesensor with 61 seconds -// //ToDo find the real conversion between TimeStampDelta and seconds -// localTimeStamp = localTimeStamp / 1300000; -// -// //Only add to stream if it is an ESPDU -// //ToDo: Add support for multiple Entities -// if ((localPdu.getPduType() != null) && (localPdu.getPduType() == DISPDUType.ENTITY_STATE)) { -// -// testMap.put((double) localTimeStamp, new Coordinates(localX, localY, localZ, localPhi, localPsi, localTheta)); -// -// } -// -// } x3dInterpolators.addPointsToMap(globalByteBufferForX3dInterPolators); x3dLineSet.addPointsToMap(globalByteBufferForX3dInterPolators); pduCount++; @@ -320,168 +234,10 @@ public class PlayerPlainText { line = brdr.readLine(); } brdr.close(); -// -// //Compression of the testMap. -// //Remove all collinear points. -// Compressor regression = new Compressor(testMap); -// -// TreeMap<Double, Coordinates> returnMap = new TreeMap<>(); -// -// //To turn of the compression just comment the next line out and the very next in. -// returnMap = regression.doCompression(); -// //returnMap.putAll(testMap); -// -// -// //Writing all values from the KeyMap to a proper Position Interpolator String -// System.out.println("Writing Position and Rotation Interpolator"); -// Set<Double> keys = returnMap.keySet(); -// //Set<Double> keys = tempKeyKeyValueSetPositionInterPolator.keySet(); -// String positionKey = "key = '"; -// String positionKeyValue = "keyValue = '"; -// String positionInterpolatorToCopy = "<PositionInterpolator DEF='EntityPosition' "; -// -// String orientationKeyX = "key = '"; -// String orientationKeyValueX = "keyValue = '"; -// String orientationInterpolatorToCopyX = "<OrientationInterpolator DEF='EntityOrientationX' "; -// -// String orientationKeyY = "key = '"; -// String orientationKeyValueY = "keyValue = '"; -// String orientationInterpolatorToCopyY = "<OrientationInterpolator DEF='EntityOrientationY' "; -// -// String orientationKeyZ = "key = '"; -// String orientationKeyValueZ = "keyValue = '"; -// String orientationInterpolatorToCopyZ = "<OrientationInterpolator DEF='EntityOrientationZ' "; -// -// //Find highest time to do the normalization -// double lastTimeStamp = 0; -// -// for (Double k : keys) { -// -// if (k > lastTimeStamp) { -// -// lastTimeStamp = k; -// -// } -// } -// -// //Normalize all times in the set -// var keyKeyValueSetPositionInterpolator = new LinkedHashMap<Double, String>(); -// -// var keyKeyValueSetOrientationInterpolatorX = new LinkedHashMap<Double, String>(); -// var keyKeyValueSetOrientationInterpolatorY = new LinkedHashMap<Double, String>(); -// var keyKeyValueSetOrientationInterpolatorZ = new LinkedHashMap<Double, String>(); -// -// for (Double k : keys) { -// -// String localCoordinateString; -// String localOrientationStringX; -// String localOrientationStringY; -// String localOrientationStringZ; -// -// double tempX = returnMap.get(k).getX(); -// double tempY = returnMap.get(k).getY(); -// double tempZ = returnMap.get(k).getZ(); -// -// double tempPhi = returnMap.get(k).getPhi()/6.28; -// double tempPsi = returnMap.get(k).getPsi()/6.28; -// double tempTheta = returnMap.get(k).getTheta()/6.28; -// -// localCoordinateString = " " + coordinateNumberFormat.format(tempX) + " " + coordinateNumberFormat.format(tempY) + " " + coordinateNumberFormat.format(tempZ); -// localOrientationStringX = " 1 0 0 " + coordinateNumberFormat.format(tempPhi); -// localOrientationStringY = " 0 1 0 " + coordinateNumberFormat.format(tempPsi); -// localOrientationStringZ = " 0 0 1 " + coordinateNumberFormat.format(tempTheta); -// -// keyKeyValueSetPositionInterpolator.put(k / lastTimeStamp, localCoordinateString); -// keyKeyValueSetOrientationInterpolatorX.put(k / lastTimeStamp, localOrientationStringX); -// keyKeyValueSetOrientationInterpolatorY.put(k / lastTimeStamp, localOrientationStringY); -// keyKeyValueSetOrientationInterpolatorZ.put(k / lastTimeStamp, localOrientationStringZ); -// -// } -// -// keys = keyKeyValueSetPositionInterpolator.keySet(); -// -// //Setting up the timeSensor -// //Only one timeSensor for both interpolators is needed -// String timeSensor = "<TimeSensor DEF='PduStreamClock' cycleInterval='"; -// -// timeSensor += lastTimeStamp; -// -// timeSensor += "' loop = 'true'/>"; -// -// //Printing the timeSensor to the console -// System.out.println(timeSensor); -// -// //Setting up PositionInterpolator and OrientationInterpolator -// for (Double k : keys) { -// //System.out.println("Time: " + k + " Position (x,y,z) " + keyKeyValueSetPositionInterpolator.get(k)); -// -// //PositionInterpolator -// positionKey += coordinateNumberFormat.format(k) + " "; -// positionKeyValue += keyKeyValueSetPositionInterpolator.get(k) + " "; -// -// //OrientationInterpolator for X -// orientationKeyX += coordinateNumberFormat.format(k) + " "; -// orientationKeyValueX += keyKeyValueSetOrientationInterpolatorX.get(k) + " "; -// -// //OrientationInterpolator for Y -// orientationKeyY += coordinateNumberFormat.format(k) + " "; -// orientationKeyValueY += keyKeyValueSetOrientationInterpolatorY.get(k) + " "; -// -// //OrientationInterpolator for Z -// orientationKeyZ += coordinateNumberFormat.format(k) + " "; -// orientationKeyValueZ += keyKeyValueSetOrientationInterpolatorZ.get(k) + " "; -// -// } -// positionKey += "' "; -// positionKeyValue += "' "; -// -// orientationKeyX += "' "; -// orientationKeyValueX += "' "; -// -// orientationKeyY += "' "; -// orientationKeyValueY += "' "; -// -// orientationKeyZ += "' "; -// orientationKeyValueZ += "' "; -// -// //PositionInterpolator -// positionInterpolatorToCopy += positionKey + "\n"; -// positionInterpolatorToCopy += positionKeyValue; -// positionInterpolatorToCopy += "/>"; -// -// //PositionInterpolator for X -// orientationInterpolatorToCopyX += orientationKeyX + "\n"; -// orientationInterpolatorToCopyX += orientationKeyValueX; -// orientationInterpolatorToCopyX += "/>"; -// -// //PositionInterpolator for Y -// orientationInterpolatorToCopyY += orientationKeyY + "\n"; -// orientationInterpolatorToCopyY += orientationKeyValueY; -// orientationInterpolatorToCopyY += "/>"; -// -// //PositionInterpolator for Z -// orientationInterpolatorToCopyZ += orientationKeyY + "\n"; -// orientationInterpolatorToCopyZ += orientationKeyValueZ; -// orientationInterpolatorToCopyZ += "/>"; -// -// //Printing PositionInterpolator to the console -// System.out.println(positionInterpolatorToCopy); -// -// //Printing OrientationInterpolator for X to the console -// System.out.println(orientationInterpolatorToCopyX); -// -// //Printing OrientationInterpolator for Y to the console -// System.out.println(orientationInterpolatorToCopyY); -// -// //Printing OrientationInterpolator for Z to the console -// System.out.println(orientationInterpolatorToCopyZ); - - - - x3dInterpolators.makeX3dInterpolator(); - x3dLineSet.makeX3dLineSet(); - - + + x3dInterpolators.makeX3dInterpolator(); + x3dLineSet.makeX3dLineSet(); + } } catch (Exception ex) { System.err.println("Exception reading/writing pdus: " + ex.getClass().getSimpleName() + ": " + ex.getLocalizedMessage()); diff --git a/BrennenstuhlTobias/src/PduStreamTools/README.md b/BrennenstuhlTobias/src/PduStreamTools/README.md new file mode 100644 index 0000000..4b4f639 --- /dev/null +++ b/BrennenstuhlTobias/src/PduStreamTools/README.md @@ -0,0 +1,5 @@ +Future Work: + +- add support for multiple entities +- connect to Framework that autogenerates nodes (instead of string output) +- add ANT build script for Unit-Testing \ No newline at end of file diff --git a/BrennenstuhlTobias/src/PduStreamTools/RecorderPlainText.java b/BrennenstuhlTobias/src/PduStreamTools/RecorderPlainText.java index 52853fa..4981f42 100644 --- a/BrennenstuhlTobias/src/PduStreamTools/RecorderPlainText.java +++ b/BrennenstuhlTobias/src/PduStreamTools/RecorderPlainText.java @@ -1,8 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package PduStreamTools; import com.google.common.primitives.Longs; @@ -22,6 +17,13 @@ import java.io.IOException; import java.nio.file.Path; import java.util.Arrays; +/** + * RecorderPlainText.java created on Mar 2, 2020 MOVES Institute Naval Postgraduate + * School, Monterey, CA, USA www.nps.edu + * + * @author Mike Bailey, jmbailey@nps.edu + * @author Tobias Brennenstuhl, tobias.brennenstuhl.gy@nps.edu + */ public class RecorderPlainText implements PduReceiver { diff --git a/BrennenstuhlTobias/src/PduStreamTools/Coordinates.java b/BrennenstuhlTobias/src/PduStreamTools/X3DCoordinates.java similarity index 74% rename from BrennenstuhlTobias/src/PduStreamTools/Coordinates.java rename to BrennenstuhlTobias/src/PduStreamTools/X3DCoordinates.java index 71f7c95..e84e23d 100644 --- a/BrennenstuhlTobias/src/PduStreamTools/Coordinates.java +++ b/BrennenstuhlTobias/src/PduStreamTools/X3DCoordinates.java @@ -1,17 +1,12 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package PduStreamTools; /** * This class is a holder for coordinates and angles of ESPDUs to store them in * HashMaps * - * @author Tobias Brennenstuhl + * @author Tobias Brennenstuhl @ NPS */ -public class Coordinates { +public class X3DCoordinates { private double x; private double y; @@ -20,7 +15,7 @@ public class Coordinates { private double psi; private double theta; - public Coordinates(double x, double y, double z, double phi, double psi, double theta) { + public X3DCoordinates(double x, double y, double z, double phi, double psi, double theta) { this.setX(x); this.setY(y); this.setZ(z); @@ -30,7 +25,7 @@ public class Coordinates { } - public Coordinates() { + public X3DCoordinates() { this.setX(0.0); this.setY(0.0); this.setZ(0.0); diff --git a/BrennenstuhlTobias/src/PduStreamTools/CreateX3dInterpolators.java b/BrennenstuhlTobias/src/PduStreamTools/X3DCreateInterpolators.java similarity index 57% rename from BrennenstuhlTobias/src/PduStreamTools/CreateX3dInterpolators.java rename to BrennenstuhlTobias/src/PduStreamTools/X3DCreateInterpolators.java index 7d5b5d5..56b546f 100644 --- a/BrennenstuhlTobias/src/PduStreamTools/CreateX3dInterpolators.java +++ b/BrennenstuhlTobias/src/PduStreamTools/X3DCreateInterpolators.java @@ -22,7 +22,7 @@ import java.util.logging.Logger; * * @author Tobias Brennenstuhl @ NPS */ -public class CreateX3dInterpolators { +public class X3DCreateInterpolators { private byte[] bufferShort; @@ -33,14 +33,17 @@ public class CreateX3dInterpolators { private double firstLocalX = 0; private double firstLocalY = 0; private double firstLocalZ = 0; + private double firstLocalPhi = 0; + private double firstLocalPsi = 0; + private double firstLocalTheta = 0; - private LinkedHashMap<Double, Coordinates> testMap = new LinkedHashMap<>(); + private LinkedHashMap<Double, X3DCoordinates> testMap = new LinkedHashMap<>(); //Setting up a NumberFormatter for limitting the decimal count to 3 private NumberFormat coordinateNumberFormat = NumberFormat.getInstance(new Locale("en", "US")); // -------------------- End Variables for Position Interpolator - public CreateX3dInterpolators() { + public X3DCreateInterpolators() { //3 significant digits equals milimeter position accuracy and 0.001 radians = 0.0572963266634555‬ degrees coordinateNumberFormat.setMaximumFractionDigits(3); @@ -52,71 +55,71 @@ public class CreateX3dInterpolators { this.bufferShort = localBufferShort.clone(); if (bufferShort[2] == 1) { - - //PDU Factory - PduFactory pduFactory = new PduFactory(); - Pdu localPdu = null; - - localPdu = pduFactory.createPdu(bufferShort); - - // ToDO figure out how to do this! makeEntityStatePDU - EntityStatePdu localEspdu = pduFactory.makeEntityStatePdu(); - //Put all the data we need into the localEspdu - ByteBuffer espduBuffer = ByteBuffer.wrap(bufferShort); - try { - localEspdu.unmarshal(espduBuffer); - } catch (Exception ex) { - Logger.getLogger(CreateX3dInterpolators.class.getName()).log(Level.SEVERE, null, ex); - } - - double localTimeStamp = 0; - double localX = 0; - double localY = 0; - double localZ = 0; - double localPhi = 0; - double localPsi = 0; - double localTheta = 0; + //PDU Factory + PduFactory pduFactory = new PduFactory(); + Pdu localPdu = null; - //Store the first timestamp to subtract it from all others - //Same with X,Y,Z to create a local coordiante system - if (firstTimeStamp) { + localPdu = pduFactory.createPdu(bufferShort); - firstLocalTimeStamp = localPdu.getTimestamp(); - localTimeStamp = localPdu.getTimestamp(); - firstLocalX = localEspdu.getEntityLocation().getX(); - firstLocalY = localEspdu.getEntityLocation().getZ(); - firstLocalZ = -1*localEspdu.getEntityLocation().getY(); + // ToDO figure out how to do this! makeEntityStatePDU + EntityStatePdu localEspdu = pduFactory.makeEntityStatePdu(); + //Put all the data we need into the localEspdu + ByteBuffer espduBuffer = ByteBuffer.wrap(bufferShort); + try { + localEspdu.unmarshal(espduBuffer); + } catch (Exception ex) { + Logger.getLogger(X3DCreateInterpolators.class.getName()).log(Level.SEVERE, null, ex); + } - firstTimeStamp = false; - } + double localTimeStamp = 0; + double localX = 0; + double localY = 0; + double localZ = 0; - localTimeStamp = localPdu.getTimestamp(); - localX = localEspdu.getEntityLocation().getX(); - localY = localEspdu.getEntityLocation().getZ(); - localZ = -1*localEspdu.getEntityLocation().getY(); - localPhi = localEspdu.getEntityOrientation().getPhi(); - localPsi = localEspdu.getEntityOrientation().getPsi(); - localTheta = localEspdu.getEntityOrientation().getTheta(); + double localPhi = 0; + double localPsi = 0; + double localTheta = 0; - localTimeStamp = localTimeStamp - firstLocalTimeStamp; - localX = localX - firstLocalX; - localY = localY - firstLocalY; - localZ = localZ - firstLocalZ; + //Store the first timestamp to subtract it from all others + //Same with X,Y,Z to create a local coordiante system + if (firstTimeStamp) { - //Divide TimeStamp by 1,300,000 to get something close to a second per Unit. - //According to the DIS standard one tick is 3600/(2^31) seconds ~ 1.6764 µs - //1,300,000 was derived from a stream that is 61 seconds long. The number was adjusted to get a timesensor with 61 seconds - //ToDo find the real conversion between TimeStampDelta and seconds - localTimeStamp = localTimeStamp / 1300000; + firstLocalTimeStamp = localPdu.getTimestamp(); + localTimeStamp = localPdu.getTimestamp(); + firstLocalX = localEspdu.getEntityLocation().getX(); + firstLocalY = localEspdu.getEntityLocation().getZ(); + firstLocalZ = -1 * localEspdu.getEntityLocation().getY(); - //Only add to stream if it is an ESPDU - //ToDo: Add support for multiple Entities - if ((localPdu.getPduType() != null) && (localPdu.getPduType() == DISPDUType.ENTITY_STATE)) { + firstTimeStamp = false; + } - testMap.put((double) localTimeStamp, new Coordinates(localX, localY, localZ, localPhi, localPsi, localTheta)); + localTimeStamp = localPdu.getTimestamp(); + localX = localEspdu.getEntityLocation().getX(); + localY = localEspdu.getEntityLocation().getZ(); + localZ = -1 * localEspdu.getEntityLocation().getY(); + localPhi = localEspdu.getEntityOrientation().getPhi(); + localPsi = localEspdu.getEntityOrientation().getPsi(); + localTheta = localEspdu.getEntityOrientation().getTheta(); + + localTimeStamp = localTimeStamp - firstLocalTimeStamp; + localX = localX - firstLocalX; + localY = localY - firstLocalY; + localZ = localZ - firstLocalZ; + + //Divide TimeStamp by 1,300,000 to get something close to a second per Unit. + //According to the DIS standard one tick is 3600/(2^31) seconds ~ 1.6764 µs + //1,100,000 was derived from a stream that is 83 seconds long. The number was adjusted to get a timesensor with 83 seconds + //ToDo find the real conversion between TimeStampDelta and seconds + localTimeStamp = localTimeStamp / 1100000; + + //Only add to stream if it is an ESPDU + //ToDo: Add support for multiple Entities + if ((localPdu.getPduType() != null) && (localPdu.getPduType() == DISPDUType.ENTITY_STATE)) { + + testMap.put((double) localTimeStamp, new X3DCoordinates(localX, localY, localZ, localPhi, localPsi, localTheta)); - } + } } } @@ -125,16 +128,16 @@ public class CreateX3dInterpolators { //Compression of the testMap. //Remove all collinear points. - SlidingWindowCompression slidingWindowCompression = new SlidingWindowCompression(testMap); + X3DSlidingWindowCompression slidingWindowCompression = new X3DSlidingWindowCompression(testMap); - TreeMap<Double, Coordinates> returnMap = new TreeMap<>(); + TreeMap<Double, X3DCoordinates> returnMap = new TreeMap<>(); //To turn of the compression just comment the next line out and the very next in. returnMap = slidingWindowCompression.doSlidingWindow(); //returnMap.putAll(testMap); //Writing all values from the KeyMap to a proper Position Interpolator String - System.out.println("Writing Position and Rotation Interpolator"); + System.out.println("Writing Position and Orientation Interpolator:"); Set<Double> keys = returnMap.keySet(); //Set<Double> keys = tempKeyKeyValueSetPositionInterPolator.keySet(); String positionKey = "key = '"; @@ -152,7 +155,12 @@ public class CreateX3dInterpolators { String orientationKeyZ = "key = '"; String orientationKeyValueZ = "keyValue = '"; String orientationInterpolatorToCopyZ = "<OrientationInterpolator DEF='EntityOrientationZ' "; - + + String waypointInterpolatorWayPoints = "value = '"; + String waypointInterpolatorLegDurations = "value = '"; + String waypointInterpolatorWayPointsToCopy = "<fieldValue name='waypoints' "; + String waypointInterpolatorLegDurationsToCopy = "<fieldValue name='legDurations' "; + //Find highest time to do the normalization double lastTimeStamp = 0; @@ -171,13 +179,18 @@ public class CreateX3dInterpolators { var keyKeyValueSetOrientationInterpolatorX = new LinkedHashMap<Double, String>(); var keyKeyValueSetOrientationInterpolatorY = new LinkedHashMap<Double, String>(); var keyKeyValueSetOrientationInterpolatorZ = new LinkedHashMap<Double, String>(); - + + var waypointInterpolatorValueSet = new LinkedHashMap<Double, String>(); + + double kLegduration = 0; + for (Double k : keys) { String localCoordinateString; String localOrientationStringX; String localOrientationStringY; String localOrientationStringZ; + String localWaypointInterpolator; double tempX = returnMap.get(k).getX(); double tempY = returnMap.get(k).getY(); @@ -189,13 +202,16 @@ public class CreateX3dInterpolators { localCoordinateString = " " + coordinateNumberFormat.format(tempX) + " " + coordinateNumberFormat.format(tempY) + " " + coordinateNumberFormat.format(tempZ); localOrientationStringX = " 1 0 0 " + coordinateNumberFormat.format(tempPhi); - localOrientationStringY = " 0 1 0 " + coordinateNumberFormat.format(tempPsi); - localOrientationStringZ = " 0 0 1 " + coordinateNumberFormat.format(tempTheta); + localOrientationStringY = " 0 1 0 " + coordinateNumberFormat.format(tempTheta); + localOrientationStringZ = " 0 0 1 " + coordinateNumberFormat.format(tempPsi); keyKeyValueSetPositionInterpolator.put(k / lastTimeStamp, localCoordinateString); keyKeyValueSetOrientationInterpolatorX.put(k / lastTimeStamp, localOrientationStringX); keyKeyValueSetOrientationInterpolatorY.put(k / lastTimeStamp, localOrientationStringY); keyKeyValueSetOrientationInterpolatorZ.put(k / lastTimeStamp, localOrientationStringZ); + + waypointInterpolatorValueSet.put(60*(k-kLegduration)/lastTimeStamp,localCoordinateString); + kLegduration = k; } @@ -210,7 +226,6 @@ public class CreateX3dInterpolators { timeSensor += "' loop = 'true'/>"; //Printing the timeSensor to the console - System.out.println(timeSensor); //Setting up PositionInterpolator and OrientationInterpolator @@ -221,19 +236,42 @@ public class CreateX3dInterpolators { positionKey += coordinateNumberFormat.format(k) + " "; positionKeyValue += keyKeyValueSetPositionInterpolator.get(k) + " "; - //OrientationInterpolator for X + //OrientationInterpolator for X (phi) orientationKeyX += coordinateNumberFormat.format(k) + " "; orientationKeyValueX += keyKeyValueSetOrientationInterpolatorX.get(k) + " "; - //OrientationInterpolator for Y + //OrientationInterpolator for Y (theta) orientationKeyY += coordinateNumberFormat.format(k) + " "; orientationKeyValueY += keyKeyValueSetOrientationInterpolatorY.get(k) + " "; - //OrientationInterpolator for Z + //OrientationInterpolator for Z (psi) orientationKeyZ += coordinateNumberFormat.format(k) + " "; orientationKeyValueZ += keyKeyValueSetOrientationInterpolatorZ.get(k) + " "; + + + } + + //WayPointInterpolator + keys = waypointInterpolatorValueSet.keySet(); + + for (Double k : keys) { + + waypointInterpolatorWayPoints += waypointInterpolatorValueSet.get(k) + " "; + + if (k!=0) { + + waypointInterpolatorLegDurations += coordinateNumberFormat.format(k) + " "; + } + } + + + + + + + positionKey += "' "; positionKeyValue += "' "; @@ -245,6 +283,9 @@ public class CreateX3dInterpolators { orientationKeyZ += "' "; orientationKeyValueZ += "' "; + + waypointInterpolatorWayPoints += "' "; + waypointInterpolatorLegDurations += "' "; //PositionInterpolator positionInterpolatorToCopy += positionKey + "\n"; @@ -265,18 +306,33 @@ public class CreateX3dInterpolators { orientationInterpolatorToCopyZ += orientationKeyY + "\n"; orientationInterpolatorToCopyZ += orientationKeyValueZ; orientationInterpolatorToCopyZ += "/>"; + + //WaypointInterpolator + waypointInterpolatorWayPointsToCopy += waypointInterpolatorWayPoints; + waypointInterpolatorWayPointsToCopy += "/>"; + + waypointInterpolatorLegDurationsToCopy += waypointInterpolatorLegDurations; + waypointInterpolatorLegDurationsToCopy += "/>"; //Printing PositionInterpolator to the console System.out.println(positionInterpolatorToCopy); + //First Rotation must be around z axis by psi //Printing OrientationInterpolator for X to the console - System.out.println(orientationInterpolatorToCopyX); + System.out.println(orientationInterpolatorToCopyZ); + //Second Rotation must be around resulting y (y') axis by theta //Printing OrientationInterpolator for Y to the console System.out.println(orientationInterpolatorToCopyY); + //last rotation must be around resulting x (x') axis by phi //Printing OrientationInterpolator for Z to the console - System.out.println(orientationInterpolatorToCopyZ); + System.out.println(orientationInterpolatorToCopyX); + + //WaypointInterpolator: + System.out.println(waypointInterpolatorWayPointsToCopy); + System.out.println(waypointInterpolatorLegDurationsToCopy); + } } diff --git a/BrennenstuhlTobias/src/PduStreamTools/CreateX3dLineSet.java b/BrennenstuhlTobias/src/PduStreamTools/X3DCreateLineSet.java similarity index 89% rename from BrennenstuhlTobias/src/PduStreamTools/CreateX3dLineSet.java rename to BrennenstuhlTobias/src/PduStreamTools/X3DCreateLineSet.java index 5a9337f..cb95656 100644 --- a/BrennenstuhlTobias/src/PduStreamTools/CreateX3dLineSet.java +++ b/BrennenstuhlTobias/src/PduStreamTools/X3DCreateLineSet.java @@ -22,7 +22,7 @@ import java.util.logging.Logger; * * @author Tobias Brennenstuhl @ NPS */ -public class CreateX3dLineSet { +public class X3DCreateLineSet { private byte[] bufferShort; @@ -34,13 +34,13 @@ public class CreateX3dLineSet { private double firstLocalY = 0; private double firstLocalZ = 0; - private LinkedHashMap<Double, Coordinates> testMap = new LinkedHashMap<>(); + private LinkedHashMap<Double, X3DCoordinates> testMap = new LinkedHashMap<>(); //Setting up a NumberFormatter for limitting the decimal count to 3 private NumberFormat coordinateNumberFormat = NumberFormat.getInstance(new Locale("en", "US")); // -------------------- End Variables for Position Interpolator - public CreateX3dLineSet() { + public X3DCreateLineSet() { //3 significant digits equals milimeter position accuracy and 0.001 radians = 0.0572963266634555‬ degrees coordinateNumberFormat.setMaximumFractionDigits(3); @@ -66,7 +66,7 @@ public class CreateX3dLineSet { try { localEspdu.unmarshal(espduBuffer); } catch (Exception ex) { - Logger.getLogger(CreateX3dLineSet.class.getName()).log(Level.SEVERE, null, ex); + Logger.getLogger(X3DCreateLineSet.class.getName()).log(Level.SEVERE, null, ex); } double localTimeStamp = 0; @@ -112,7 +112,7 @@ public class CreateX3dLineSet { //ToDo: Add support for multiple Entities if ((localPdu.getPduType() != null) && (localPdu.getPduType() == DISPDUType.ENTITY_STATE)) { - testMap.put((double) localTimeStamp, new Coordinates(localX, localY, localZ, 0.0, 0.0, 0.0)); + testMap.put((double) localTimeStamp, new X3DCoordinates(localX, localY, localZ, 0.0, 0.0, 0.0)); } } @@ -123,9 +123,9 @@ public class CreateX3dLineSet { //Compression of the testMap. //Remove all collinear points. - SlidingWindowCompression regression = new SlidingWindowCompression(testMap); + X3DSlidingWindowCompression regression = new X3DSlidingWindowCompression(testMap); - TreeMap<Double, Coordinates> returnMap = new TreeMap<>(); + TreeMap<Double, X3DCoordinates> returnMap = new TreeMap<>(); //To turn of the compression just comment the next line out and the very next in. returnMap = regression.doSlidingWindow(); diff --git a/BrennenstuhlTobias/src/PduStreamTools/SlidingWindowCompression.java b/BrennenstuhlTobias/src/PduStreamTools/X3DSlidingWindowCompression.java similarity index 68% rename from BrennenstuhlTobias/src/PduStreamTools/SlidingWindowCompression.java rename to BrennenstuhlTobias/src/PduStreamTools/X3DSlidingWindowCompression.java index ac8a50d..7fd860f 100644 --- a/BrennenstuhlTobias/src/PduStreamTools/SlidingWindowCompression.java +++ b/BrennenstuhlTobias/src/PduStreamTools/X3DSlidingWindowCompression.java @@ -1,8 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package PduStreamTools; import static java.lang.Math.pow; @@ -15,48 +10,33 @@ import java.util.TreeMap; /** * - * @author tobia + * @author Tobias Brennenstuhl @ NPS */ -public class SlidingWindowCompression { +public class X3DSlidingWindowCompression { - private LinkedHashMap<Double, Coordinates> localMap; + private LinkedHashMap<Double, X3DCoordinates> localMap; - public SlidingWindowCompression(LinkedHashMap<Double, Coordinates> localHashMap) { + public X3DSlidingWindowCompression(LinkedHashMap<Double, X3DCoordinates> localHashMap) { - //copy the given HashMap to a localMap this.localMap = new LinkedHashMap<>(); - Set<Double> keys = localHashMap.keySet(); - for (Double k : keys) { - localMap.put(k, localHashMap.get(k)); - } - - //System.out.println("DISTools.Regression.<init>()"); - } - public TreeMap<Double, Coordinates> doSlidingWindow() { + public TreeMap<Double, X3DCoordinates> doSlidingWindow() { System.out.println("DISTools.Regression.doRegression()"); - //Check whether points could be deleted to compress the stream //https://www.crashkurs-statistik.de/einfache-lineare-regression/ - TreeMap<Double, Coordinates> streamMap = new TreeMap<>(); - - Set<Double> keys = localMap.keySet(); - + TreeMap<Double, X3DCoordinates> streamMap = new TreeMap<>(); //Copy LinkedHashMap into TreeMap to be able to pull the first element. streamMap.putAll(localMap); - - TreeMap<Double, Coordinates> returnMap = new TreeMap<>(); + TreeMap<Double, X3DCoordinates> returnMap = new TreeMap<>(); //TreeMap of slidingWindows will store all of the points that are currently processed //use .pullFirstEntry() to get rid of the points at the beginning. - TreeMap<Double, Coordinates> slidingWindow = new TreeMap<>(); - - boolean addToWindow = true; + TreeMap<Double, X3DCoordinates> slidingWindow = new TreeMap<>(); while (streamMap.size() > 0) { slidingWindow.put(streamMap.firstEntry().getKey(), streamMap.get(streamMap.firstEntry().getKey())); @@ -74,52 +54,36 @@ public class SlidingWindowCompression { List<Double> phiList = new ArrayList<>(); List<Double> psiList = new ArrayList<>(); List<Double> thetaList = new ArrayList<>(); - - Double[] k = new Double[slidingWindowKeys.size()]; slidingWindowKeys.toArray(k); for (int i = 0; i < slidingWindow.size(); i++) { - //Fix Loop to fill Arrays tList.add(i, k[i]); - - phiList.add(i, slidingWindow.get(k[i]).getPhi()); + phiList.add(i, slidingWindow.get(k[i]).getPhi()); psiList.add(i, slidingWindow.get(k[i]).getPsi()); - thetaList.add(i, slidingWindow.get(k[i]).getTheta()); - xList.add(i, slidingWindow.get(k[i]).getX()); - yList.add(i, slidingWindow.get(k[i]).getY()); - zList.add(i, slidingWindow.get(k[i]).getZ()); - - + } - //calculate triangle according to the homepage + //Calculate Area of Triangle + //Credit: http://www.ambrsoft.com/TrigoCalc/Line3D/LineColinear.htm for (int i = 0; i < slidingWindow.size(); i++) { - //Calculate Area of Triangle - //http://www.ambrsoft.com/TrigoCalc/Line3D/LineColinear.htm double a = sqrt(pow(xList.get(1) - xList.get(0), 2) + pow(yList.get(1) - yList.get(0), 2) + pow(zList.get(1) - zList.get(0), 2)); double b = sqrt(pow(xList.get(i) - xList.get(0), 2) + pow(yList.get(i) - yList.get(0), 2) + pow(zList.get(i) - zList.get(0), 2)); double c = sqrt(pow(xList.get(i) - xList.get(1), 2) + pow(yList.get(i) - yList.get(1), 2) + pow(zList.get(i) - zList.get(1), 2)); - double s = (a + b + c) / 2; - double areaA = sqrt(s * (s - a) * (s - b) * (s - c)); if ((areaA >= 0.1) || (tList.get(i) - tList.get(0) >= 4.0)) { - - //@Debug - //System.out.println("Threshold met. Break"); - //grab the first and the last point from the sliding window and push it to the returnMap - Coordinates firstPoint = new Coordinates(); + X3DCoordinates firstPoint = new X3DCoordinates(); firstPoint.setX(xList.get(0)); firstPoint.setY(yList.get(0)); firstPoint.setZ(zList.get(0)); @@ -127,8 +91,7 @@ public class SlidingWindowCompression { firstPoint.setPsi(psiList.get(0)); firstPoint.setTheta(thetaList.get(0)); - //ToDo add the angles to the Coordinates - Coordinates lastPoint = new Coordinates(xList.get(i), yList.get(i), zList.get(i), phiList.get(i), psiList.get(i), thetaList.get(i)); + X3DCoordinates lastPoint = new X3DCoordinates(xList.get(i), yList.get(i), zList.get(i), phiList.get(i), psiList.get(i), thetaList.get(i)); returnMap.put(tList.get(0), firstPoint); returnMap.put(tList.get(i), lastPoint); @@ -142,7 +105,6 @@ public class SlidingWindowCompression { phiList.clear(); psiList.clear(); thetaList.clear(); - break; } @@ -150,22 +112,15 @@ public class SlidingWindowCompression { if ((areaA <= 0.1) && (tList.get(i) - tList.get(0) <= 4.0) && streamMap.size() == 0) { //System.out.println("StreamMap empty. All points left will be added. Break"); - - //grab the first and the last point from the regression test and push it to the returnMap + //grab the first and the last point from the siding window and push it to the returnMap for (int j = 0; j < slidingWindow.size(); j++) { - - //ToDo: Add the angles to the coordinates - Coordinates leftPoints = new Coordinates(xList.get(j), yList.get(j), zList.get(j), phiList.get(j), psiList.get(j), thetaList.get(j)); - + X3DCoordinates leftPoints = new X3DCoordinates(xList.get(j), yList.get(j), zList.get(j), phiList.get(j), psiList.get(j), thetaList.get(j)); returnMap.put(tList.get(j), leftPoints); - } break; } - //System.out.println("Area of Triangle: " + areaA); - } } @@ -175,12 +130,6 @@ public class SlidingWindowCompression { return returnMap; } - - ; - - private void calcValues() { - - } ; } -- GitLab