diff --git a/projects/Assignments/AngelBlankFP/EspduReceiverB.java b/projects/Assignments/AngelBlankFP/EspduReceiverB.java
deleted file mode 100644
index d63205138f4f44350d34f10611df6edea73d58fd..0000000000000000000000000000000000000000
--- a/projects/Assignments/AngelBlankFP/EspduReceiverB.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package java.edu.nps.moves.examples;
-
-import java.net.*;
-import java.util.*;
-
-import edu.nps.moves.disutil.*;
-
-import edu.nps.moves.dis.*;
-
-/**
- * Receives PDUs from the network in IEEE format.
- *
- * @author DMcG
- * @version $Id:$
- */
-public class EspduReceiverB {
-
-    /** Max size of a PDU in binary format that we can receive. This is actually
-     * somewhat outdated--PDUs can be larger--but this is a reasonable starting point
-     */
-    public static final int MAX_PDU_SIZE = 8192;
-
-    public static void main(String args[]) {
-        MulticastSocket socket;
-        DatagramPacket packet;
-        InetAddress address;
-        PduFactory pduFactory = new PduFactory();
-
-        try {
-            // Specify the socket to receive data
-            socket = new MulticastSocket(3001);
-            socket.setBroadcast(true);
-       
-            //address = InetAddress.getByName(EspduSender.DEFAULT_MULTICAST_GROUP);
-            //socket.joinGroup(address);
-
-            // Loop infinitely, receiving datagrams
-            while (true) {
-                byte buffer[] = new byte[MAX_PDU_SIZE];
-                packet = new DatagramPacket(buffer, buffer.length);
-
-                socket.receive(packet);
-
-                List<Pdu> pduBundle = pduFactory.getPdusFromBundle(packet.getData());
-                System.out.println("Bundle size is " + pduBundle.size());
-                
-                Iterator it = pduBundle.iterator();
-
-                while(it.hasNext())
-                {
-                    Pdu aPdu = (Pdu)it.next();
-                
-                    System.out.print("got PDU of type: " + aPdu.getClass().getName());
-                    if(aPdu instanceof EntityStatePdu)
-                    {
-                        EntityID eid = ((EntityStatePdu)aPdu).getEntityID();
-                        Vector3Double position = ((EntityStatePdu)aPdu).getEntityLocation();
-                        System.out.print(" EID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
-                        System.out.print(" Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "]");
-                    }
-                    System.out.println();
-                } // end trop through PDU bundle
-
-            } // end while
-        } // End try
-        catch (Exception e) {
-
-            System.out.println(e);
-        }
-
-
-    } // end main
-} // end class
diff --git a/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardSnellPositionReceiver.java b/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardSnellPositionReceiver.java
new file mode 100644
index 0000000000000000000000000000000000000000..f756d49fcf0b7b6f9285908eafa5e3b89599453a
--- /dev/null
+++ b/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardSnellPositionReceiver.java
@@ -0,0 +1,39 @@
+//package PositionClient;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+/**
+ *
+ * @author AJSNELL
+ */
+public class ConardSnellPositionReceiver {
+    /**
+     * @param args the command line arguments
+     * @throws java.io.IOException
+     */
+    public static void main(String[] args) throws IOException {
+        String hostName = args[0];
+        try (Socket clientSocket = new Socket(hostName, 8005);
+                PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
+                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
+                BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in))) {
+                    String userInput;
+                    out.println("unit id: 1\nunit pos: 11S MS 4859 9849");
+                    while ((userInput = stdIn.readLine()) != null) {
+                        out.println(userInput);
+                        System.out.println("from client: " + in.readLine());
+                    }
+        } catch (UnknownHostException e) {
+            System.err.println("Don't know about host " + hostName);
+            System.exit(1);
+        } catch (IOException e) {
+            System.err.println("Couldn't get I/O for the connection to " + hostName);
+            System.exit(1);
+        }
+    }
+}
\ No newline at end of file
diff --git a/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardSnellPositionSender.java b/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardSnellPositionSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..4a77d3525650e99e84442cdf592556cdfd3967b7
--- /dev/null
+++ b/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardSnellPositionSender.java
@@ -0,0 +1,30 @@
+//package positionserver;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.io.PrintWriter;
+
+public class ConardSnellPositionSender {
+    /**
+     * @param args the command line arguments
+     * @throws java.io.IOException
+     */
+    public static void main(String[] args) throws IOException {
+        try (ServerSocket serverSocket = new ServerSocket(8005);
+                Socket clientSocket = serverSocket.accept();
+                PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
+                BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));) {
+            System.out.println("Client connected on port 8005");
+            String inputLine;
+            while ((inputLine = in.readLine()) != null) {
+                System.out.println("Received message: " + inputLine + " from " + clientSocket.toString());
+                out.println(inputLine);
+            }
+        } catch (IOException e) {
+            System.out.println("Exception when trying to listen on port 8005");
+        }
+    }
+}
\ No newline at end of file
diff --git a/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardSnellREADME.md b/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardSnellREADME.md
new file mode 100644
index 0000000000000000000000000000000000000000..a704e52cd0e75e5a801b3642b756d0b74085a1da
--- /dev/null
+++ b/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardSnellREADME.md
@@ -0,0 +1,7 @@
+## Final Course Projects 2018March
+
+Create a dedicated subdirectory for each individual or team project.
+
+Example:  `SmithJones`
+
+See the course syllabus for details on how to document your project.
diff --git a/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardTcpClient.java b/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardTcpClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..37d674b3a4f76a38c24bb2852217e20b019838f9
--- /dev/null
+++ b/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardTcpClient.java
@@ -0,0 +1,52 @@
+//package tcpclient;
+
+import java.io.*;
+import java.net.*;
+
+/**
+ * Before, we always used telnet to connect to the server. We
+ * are now writing our own program to do the connection.
+ * 
+ * As you will see, when we run this after we start the server
+ * we will see the same string telnet printed, sent by the server.
+ * The output at the server will show different socket pairs for
+ * each time we ran it.
+ * 
+ * @author mcgredo
+ */
+public class ConardTcpClient {
+
+  
+    public static void main(String[] args) 
+    {
+        try
+        {
+           System.out.println("creating socket");
+           
+           // We request an IP to connect to ("localhost") and
+           // port number at that IP (2317). This establishes
+           // a connection to that IP in the form of the Socket
+           // object; the server uses a ServerSocket to wait for
+           // connections.
+           Socket socket = new Socket("localhost", 2317); 
+           
+           // Read the single line written by the server. We'd
+           // do things a bit differently if many lines to be read
+           // from the server, instead of one only.
+           InputStream is = socket.getInputStream();
+           InputStreamReader isr = new InputStreamReader(is);
+           BufferedReader br = new BufferedReader(isr);
+           
+           String serverMessage = br.readLine();
+           System.out.println("What is your location?    " + serverMessage);
+           
+        }
+        catch(Exception e)
+        {
+            System.out.println(e);
+            System.out.println("Problem with client");
+        }
+
+    }
+    
+}
diff --git a/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardTcpServer.java b/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardTcpServer.java
new file mode 100644
index 0000000000000000000000000000000000000000..13af5422902228c72ed99ff68af02284849968fb
--- /dev/null
+++ b/projects/Assignments/FinalProjects/2018March/ConardSnell/ConardTcpServer.java
@@ -0,0 +1,84 @@
+//package tcpserver;
+
+import java.io.*;
+import java.net.*;
+
+/**
+ * Very slightly more complex than example1. A complete copy of
+ * example 2. The only thing this does
+ * differently is introduce a loop into the response, so you don't
+ * have to restart the program after one response. Also, it prints
+ * out the socket pair the server sees. Run the program via telnet
+ * several times and compare the socket pairs.
+ * 
+ * telnet localhost 2317
+ * 
+ * If you're sophisticated you can contact the instructor's computer
+ * while running this program.
+ * 
+ * telnet <ipOfServersLaptop> 2317
+ * 
+ * And have him display the socket pairs he got.
+ * @author mcgredo
+ */
+public class ConardTcpServer 
+{
+
+    public static void main(String[] args) 
+    {
+        try
+        {
+            // ServerSocket waits for a connection from a client. 
+            // Notice that it is outside the loop; ServerSocket
+            // needs to be made only once.
+            
+            ServerSocket serverSocket = new ServerSocket(2317);
+//            System.out.println("socketCreated"); 
+
+            // Loop, infinitely, waiting for client connections.
+            // Stop the program somewhere else.
+            while(true)
+            {
+                Socket clientConnection = serverSocket.accept();
+                OutputStream os = clientConnection.getOutputStream();
+                PrintStream ps = new PrintStream(os);
+
+                ps.println("My location is 1,2,5");
+                
+                // Print some information locally about the Socket
+                // connection. This includes the port and IP numbers
+                // on both sides (the socket pair.)
+                
+                InetAddress localAddress = clientConnection.getLocalAddress();
+                InetAddress remoteAddress = clientConnection.getInetAddress();
+                
+                int localPort = clientConnection.getLocalPort();
+                int remotePort = clientConnection.getPort();
+                
+                // My socket pair connection looks like this, to localhost:
+                // Socket pair: (( /0:0:0:0:0:0:0:1, 2317 ), ( /0:0:0:0:0:0:0:1, 54876 ))
+                // Socket pair: (( /0:0:0:0:0:0:0:1, 2317 ), ( /0:0:0:0:0:0:0:1, 54881 ))
+                //
+                // Why is the first IP/port the same, while the second set has
+                // different ports?
+
+
+                System.out.println("Socket pair: (( " + localAddress.toString() + ", " + localPort + " ), ( " + 
+                        remoteAddress.toString() + ", " + remotePort + " ))");
+                
+                // Notice the use of flush() and close(). Without
+                // the close() to Socket object may stay open for 
+                // a while after the client has stopped needing this
+                // connection. Close() explicitly ends the connection.
+                ps.flush();
+                clientConnection.close();
+            }
+       }
+        catch(Exception e)
+        {
+            System.out.println("problem with networking");
+        }
+       
+    }
+    
+}
\ No newline at end of file
diff --git a/projects/Assignments/homework1/BlankenbekerMyTcpServer.java b/projects/Assignments/homework1/BlankenbekerMyTcpServer.java
index 4dc227890b63db663d542795fc12b6a4bf95a6b1..a595ef3089f22afebc38391242075080204c31a6 100644
--- a/projects/Assignments/homework1/BlankenbekerMyTcpServer.java
+++ b/projects/Assignments/homework1/BlankenbekerMyTcpServer.java
@@ -33,12 +33,12 @@ public class BlankenbekerMyTcpServer
             // needs to be made only once.
             int connectionCount = 0;
             ServerSocket serverSocket = new ServerSocket(2317);
-
+            Socket clientConnection = serverSocket.accept();
             // Loop, infinitely, waiting for client connections.
             // Stop the program somewhere else.
             while(true)
             {
-                Socket clientConnection = serverSocket.accept();
+               
                 
                 OutputStream os = clientConnection.getOutputStream();
                 PrintStream ps = new PrintStream(os);
diff --git a/projects/Assignments/homework3/ABEspduReceiverA.java b/projects/Assignments/homework3/ABEspduReceiverA.java
deleted file mode 100644
index 7b28b2b368975e266954717d0c0ea5955769bf8b..0000000000000000000000000000000000000000
--- a/projects/Assignments/homework3/ABEspduReceiverA.java
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-import java.net.*;
-import java.util.*;
-
-import edu.nps.moves.disutil.*;
-
-import edu.nps.moves.dis.*;
-
-/**
- * Receives PDUs from the network in IEEE format.
- *
- * @author DMcG
- * @version $Id:$
- */
-public class ABEspduReceiverA {
-
-    /** Max size of a PDU in binary format that we can receive. This is actually
-     * somewhat outdated--PDUs can be larger--but this is a reasonable starting point
-     */
-    public static final int MAX_PDU_SIZE = 8192;
-    public static final String GROUP = "239.1.2.3";
-    public static void main(String args[]) {
-        MulticastSocket socket;
-        DatagramPacket packet;
-        InetAddress address;
-        PduFactory pduFactory = new PduFactory();
-
-        try {
-            // Specify the socket to receive data
-            socket = new MulticastSocket(3000);
-            socket.setBroadcast(true);
-       
-            address = InetAddress.getByName(GROUP);
-            socket.joinGroup(address);
-
-            // Loop infinitely, receiving datagrams
-            while (true) {
-                byte buffer[] = new byte[MAX_PDU_SIZE];
-                packet = new DatagramPacket(buffer, buffer.length);
-
-                socket.receive(packet);
-
-                List<Pdu> pduBundle = pduFactory.getPdusFromBundle(packet.getData());
-                System.out.println("Bundle size is " + pduBundle.size());
-                
-                Iterator it = pduBundle.iterator();
-
-                while(it.hasNext())
-                {
-                    Pdu aPdu = (Pdu)it.next();
-                
-                    System.out.print("got PDU of type: " + aPdu.getClass().getName());
-                    if(aPdu instanceof EntityStatePdu)
-                    {
-                        EntityID eid = ((EntityStatePdu)aPdu).getEntityID();
-                        Vector3Double position = ((EntityStatePdu)aPdu).getEntityLocation();
-                        System.out.print(" EID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
-                        System.out.print(" Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "]");
-                    }
-                    System.out.println();
-                } // end trop through PDU bundle
-
-            } // end while
-        } // End try
-        catch (Exception e) {
-
-            System.out.println(e);
-        }
-
-
-    } // end main
-} // end class
diff --git a/projects/Assignments/homework3/ABEspduReceiverB.java b/projects/Assignments/homework3/ABEspduReceiverB.java
deleted file mode 100644
index c19654ecc603a97eda1e0846fa0ec48c3665dc46..0000000000000000000000000000000000000000
--- a/projects/Assignments/homework3/ABEspduReceiverB.java
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-import java.net.*;
-import java.util.*;
-
-import edu.nps.moves.disutil.*;
-import edu.nps.moves.dis.*;
-
-/**
- * Receives PDUs from the network in IEEE format.
- *
- * @author DMcG
- * @version $Id:$
- */
-public class ABEspduReceiverB {
-
-    /** Max size of a PDU in binary format that we can receive. This is actually
-     * somewhat outdated--PDUs can be larger--but this is a reasonable starting point
-     */
-    public static final int MAX_PDU_SIZE = 8192;
-    
-    public static final String GROUP = "239.1.2.3";
-
-    public static void main(String args[]) {
-        MulticastSocket socket;
-        DatagramPacket packet;
-        InetAddress address;
-        PduFactory pduFactory = new PduFactory();
-
-        try {
-            // Specify the socket to receive data
-            socket = new MulticastSocket(3000);
-            socket.setBroadcast(true);
-       
-
-            address = InetAddress.getByName(GROUP);
-            socket.joinGroup(address);
-
-            // Loop infinitely, receiving datagrams
-            while (true) {
-                byte buffer[] = new byte[MAX_PDU_SIZE];
-                packet = new DatagramPacket(buffer, buffer.length);
-
-                socket.receive(packet);
-
-                List<Pdu> pduBundle = pduFactory.getPdusFromBundle(packet.getData());
-                System.out.println("Bundle size is " + pduBundle.size());
-                
-                Iterator it = pduBundle.iterator();
-
-                while(it.hasNext())
-                {
-                    Pdu aPdu = (Pdu)it.next();
-                
-                    System.out.print("got PDU of type: " + aPdu.getClass().getName());
-                    if(aPdu instanceof EntityStatePdu)
-                    {
-                        EntityID eid = ((EntityStatePdu)aPdu).getEntityID();
-                        Vector3Double position = ((EntityStatePdu)aPdu).getEntityLocation();
-                        System.out.print(" EID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
-                        System.out.print(" Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "]");
-                    }
-                    System.out.println();
-                } // end trop through PDU bundle
-
-            } // end while
-        } // End try
-        catch (Exception e) {
-
-            System.out.println(e);
-        }
-
-
-    } // end main
-} // end class
diff --git a/projects/Assignments/homework3/AngelBlank/ABEspduReceiverA.java b/projects/Assignments/homework3/AngelBlank/ABEspduReceiverA.java
deleted file mode 100644
index 14fa3eb227c44a20f81d48d61739c3c18c155a8f..0000000000000000000000000000000000000000
--- a/projects/Assignments/homework3/AngelBlank/ABEspduReceiverA.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package AngelBlank;
-
-import java.net.*;
-import java.util.*;
-
-import edu.nps.moves.disutil.*;
-import edu.nps.moves.dis.*;
-
-/**
- * Receives PDUs from the network in IEEE format.
- *
- * @author DMcG
- * @version $Id:$
- */
-public class ABEspduReceiverA {
-
-    /** Max size of a PDU in binary format that we can receive. This is actually
-     * somewhat outdated--PDUs can be larger--but this is a reasonable starting point
-     */
-    public static final int MAX_PDU_SIZE = 8192;
-    public static final String GROUP = "239.1.2.3";
-    public static void main(String args[]) {
-        MulticastSocket socket;
-        DatagramPacket packet;
-        InetAddress address;
-        PduFactory pduFactory = new PduFactory();
-        
-        
-
-        try {
-            // Create TCP Bridge
-             ServerSocket serverSocket = new ServerSocket(2999);
-            
-            
-            
-            // Specify the socket to receive data
-            socket = new MulticastSocket(3000);
-            socket.setBroadcast(true);
-       
-            address = InetAddress.getByName(GROUP);
-            socket.joinGroup(address);
-
-            // Loop infinitely, receiving datagrams
-            while (true) {
-                byte buffer[] = new byte[MAX_PDU_SIZE];
-                packet = new DatagramPacket(buffer, buffer.length);
-
-                socket.receive(packet);
-
-                List<Pdu> pduBundle = pduFactory.getPdusFromBundle(packet.getData());
-                System.out.println("Bundle size is " + pduBundle.size());
-                
-                Iterator it = pduBundle.iterator();
-
-                while(it.hasNext())
-                {
-                    Pdu aPdu = (Pdu)it.next();
-                
-                    System.out.print("got PDU of type: " + aPdu.getClass().getName());
-                    if(aPdu instanceof EntityStatePdu)
-                    {
-                        EntityID eid = ((EntityStatePdu)aPdu).getEntityID();
-                        Vector3Double position = ((EntityStatePdu)aPdu).getEntityLocation();
-                        System.out.print(" EID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
-                        System.out.print(" Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "]");
-                    }
-                    System.out.println();
-                } // end trop through PDU bundle
-
-            } // end while
-        } // End try
-        catch (Exception e) {
-
-            System.out.println(e);
-        }
-
-
-    } // end main
-} // end class
diff --git a/projects/Assignments/homework3/AngelBlank/ABEspduReceiverB.java b/projects/Assignments/homework3/AngelBlank/ABEspduReceiverB.java
deleted file mode 100644
index 07c9b290455af164b3475b829ae44598eb20179b..0000000000000000000000000000000000000000
--- a/projects/Assignments/homework3/AngelBlank/ABEspduReceiverB.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package AngelBlank;
-
-
-import java.net.*;
-import java.util.*;
-
-import edu.nps.moves.disutil.*;
-import edu.nps.moves.dis.*;
-
-/**
- * Receives PDUs from the network in IEEE format.
- *
- * @author DMcG
- * @version $Id:$
- */
-public class ABEspduReceiverB {
-
-    /** Max size of a PDU in binary format that we can receive. This is actually
-     * somewhat outdated--PDUs can be larger--but this is a reasonable starting point
-     */
-    public static final int MAX_PDU_SIZE = 8192;
-    
-    public static final String GROUP = "239.1.2.3";
-
-    public static void main(String args[]) {
-        MulticastSocket socket;
-        DatagramPacket packet;
-        InetAddress address;
-        PduFactory pduFactory = new PduFactory();
-
-        try {
-            // Specify the socket to receive data
-            socket = new MulticastSocket(3000);
-            socket.setBroadcast(true);
-       
-
-            address = InetAddress.getByName(GROUP);
-            socket.joinGroup(address);
-
-            // Loop infinitely, receiving datagrams
-            while (true) {
-                byte buffer[] = new byte[MAX_PDU_SIZE];
-                packet = new DatagramPacket(buffer, buffer.length);
-
-                socket.receive(packet);
-
-                List<Pdu> pduBundle = pduFactory.getPdusFromBundle(packet.getData());
-                System.out.println("Bundle size is " + pduBundle.size());
-                
-                Iterator it = pduBundle.iterator();
-
-                while(it.hasNext())
-                {
-                    Pdu aPdu = (Pdu)it.next();
-                
-                    System.out.print("got PDU of type: " + aPdu.getClass().getName());
-                    if(aPdu instanceof EntityStatePdu)
-                    {
-                        EntityID eid = ((EntityStatePdu)aPdu).getEntityID();
-                        Vector3Double position = ((EntityStatePdu)aPdu).getEntityLocation();
-                        System.out.print(" EID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
-                        System.out.print(" Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "]");
-                    }
-                    System.out.println();
-                } // end trop through PDU bundle
-
-            } // end while
-        } // End try
-        catch (Exception e) {
-
-            System.out.println(e);
-        }
-
-
-    } // end main
-} // end class
diff --git a/projects/Assignments/homework3/AngelBlank/ABEspduSenderB.java b/projects/Assignments/homework3/AngelBlank/ABEspduSenderB.java
deleted file mode 100644
index c562c08720f8393185c735366975a341e6231bb8..0000000000000000000000000000000000000000
--- a/projects/Assignments/homework3/AngelBlank/ABEspduSenderB.java
+++ /dev/null
@@ -1,323 +0,0 @@
-package AngelBlank;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import edu.nps.moves.dis.*;
-import edu.nps.moves.disutil.CoordinateConversions;
-import edu.nps.moves.disutil.DisTime;
-
-/**
- * Creates and sends ESPDUs in IEEE binary format. 
- *
- * @author DMcG
- */
-public class ABEspduSenderB 
-{
-    public static final int NUMBER_TO_SEND = 5000;
-
-    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
-
-    /** default multicast group we send on */
-    public static final String DEFAULT_MULTICAST_GROUP = "239.1.2.3";
-   
-    /** Port we send on */
-    public static final int    DIS_DESTINATION_PORT = 3000;
-    
-/** Possible system properties, passed in via -Dattr=val
-     * networkMode: unicast, broadcast, multicast
-     * destinationIp: where to send the packet. If in multicast mode, this can be mcast.
-     *                To determine bcast destination IP, use an online bcast address
-     *                caclulator, for example http://www.remotemonitoringsystems.ca/broadcast.php
-     *                If in mcast mode, a join() will be done on the mcast address.
-     * port: port used for both source and destination.
-     * @param args 
-     */
-public static void main(String args[])
-{
-    /** an entity state pdu */
-    EntityStatePdu espdu = new EntityStatePdu();
-    MulticastSocket socket = null;
-    DisTime disTime = DisTime.getInstance();
-    int alternator = -1;
-    
-    // ICBM coordinates for my office
-    double lat = 36.595517; 
-    double lon = -121.877000;
-
-    
-    // Default settings. These are used if no system properties are set. 
-    // If system properties are passed in, these are over ridden.
-    int port = DIS_DESTINATION_PORT;
-    NetworkMode mode = NetworkMode.MULTICAST;
-    InetAddress destinationIp = null;
-    
-    try
-    {
-        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
-    }
-    catch(Exception e)
-    {
-        System.out.println(e + " Cannot create multicast address");
-        System.exit(0);
-    }
-    
-    // All system properties, passed in on the command line via -Dattribute=value
-    Properties systemProperties = System.getProperties();
-    
-    // IP address we send to
-    String destinationIpString = systemProperties.getProperty("destinationIp");
-    
-    // Port we send to, and local port we open the socket on
-    String portString = systemProperties.getProperty("port");
-    
-    // Network mode: unicast, multicast, broadcast
-    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
-        
-
-    // Set up a socket to send information
-    try
-    {
-        // Port we send to
-        if(portString != null)
-            port = Integer.parseInt(portString);
-        
-        socket = new MulticastSocket(port);
-        
-        // Where we send packets to, the destination IP address
-        if(destinationIpString != null)
-        {
-            destinationIp = InetAddress.getByName(destinationIpString);
-        }
-
-        // Type of transport: unicast, broadcast, or multicast
-        if(networkModeString != null)
-        {
-            if(networkModeString.equalsIgnoreCase("unicast"))
-                mode = NetworkMode.UNICAST;
-            else if(networkModeString.equalsIgnoreCase("broadcast"))
-                mode = NetworkMode.BROADCAST;
-            else if(networkModeString.equalsIgnoreCase("multicast"))
-            {
-                mode = NetworkMode.MULTICAST;
-                if(!destinationIp.isMulticastAddress())
-                {
-                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
-                }
-                
-                socket.joinGroup(destinationIp);
-                
-            }
-        } // end networkModeString
-    }
-    catch(Exception e)
-    {
-        System.out.println("Unable to initialize networking. Exiting.");
-        System.out.println(e);
-        System.exit(-1);
-    }
-    
-    // Initialize values in the Entity State PDU object. The exercise ID is 
-    // a way to differentiate between different virtual worlds on one network.
-    // Note that some values (such as the PDU type and PDU family) are set
-    // automatically when you create the ESPDU.
-    espdu.setExerciseID((short)1);
-    
-    // The EID is the unique identifier for objects in the world. This 
-    // EID should match up with the ID for the object specified in the 
-    // VMRL/x3d/virtual world.
-    EntityID eid = espdu.getEntityID();
-    eid.setSite(1);  // 0 is apparently not a valid site number, per the spec
-    eid.setApplication(1); 
-    eid.setEntity(2); 
-    
-    // Set the entity type. SISO has a big list of enumerations, so that by
-    // specifying various numbers we can say this is an M1A2 American tank,
-    // the USS Enterprise, and so on. We'll make this a tank. There is a 
-    // separate project elsehwhere in this project that implements DIS 
-    // enumerations in C++ and Java, but to keep things simple we just use
-    // numbers here.
-    EntityType entityType = espdu.getEntityType();
-    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
-    entityType.setCountry(225);              // USA
-    entityType.setDomain((short)1);          // Land (vs air, surface, subsurface, space)
-    entityType.setCategory((short)1);        // Tank
-    entityType.setSubcategory((short)1);     // M1 Abrams
-    entityType.setSpec((short)3);            // M1A2 Abrams
-    
-
-    Set<InetAddress> bcastAddresses = getBroadcastAddresses();
-    // Loop through sending N ESPDUs
-    try
-    {
-        System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
-        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
-        {
-            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
-            // hour, and time is set to DIS time units from the top of the hour. 
-            // This means that if you start sending just before the top of the hour
-            // the time units can roll over to zero as you are sending. The receivers
-            // (escpecially homegrown ones) are often not able to detect rollover
-            // and may start discarding packets as dupes or out of order. We use
-            // an NPS timestamp here, hundredths of a second since the start of the
-            // year. The DIS standard for time is often ignored in the wild; I've seen
-            // people use Unix time (seconds since 1970) and more. Or you can
-            // just stuff idx into the timestamp field to get something that is monotonically
-            // increasing.
-            
-            // Note that timestamp is used to detect duplicate and out of order packets. 
-            // That means if you DON'T change the timestamp, many implementations will simply
-            // discard subsequent packets that have an identical timestamp. Also, if they
-            // receive a PDU with an timestamp lower than the last one they received, they
-            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
-            // update the timestamp on ALL packets sent.
-            
-
-            // An alterative approach: actually follow the standard. It's a crazy concept,
-            // but it might just work.
-            int ts = disTime.getDisAbsoluteTimestamp();
-            espdu.setTimestamp(ts);
-            
-            // Set the position of the entity in the world. DIS uses a cartesian 
-            // coordinate system with the origin at the center of the earth, the x
-            // axis out at the equator and prime meridian, y out at the equator and
-            // 90 deg east, and z up and out the north pole. To place an object on
-            // the earth's surface you also need a model for the shape of the earth
-            // (it's not a sphere.) All the fancy math necessary to do this is in
-            // the SEDRIS SRM package. There are also some one-off formulas for 
-            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
-            // Here we use those one-off formulas.
-
-            // Modify the position of the object. This will send the object a little
-            // due east by adding some to the longitude every iteration. Since we
-            // are on the Pacific coast, this sends the object east. Assume we are
-            // at zero altitude. In other worlds you'd use DTED to determine the
-            // local ground altitude at that lat/lon, or you'd just use ground clamping.
-            // The x and y values will change, but the z value should not.
-            
-            //lon = lon + (double)((double)idx / 100000.0);
-            //System.out.println("lla=" + lat + "," + lon + ", 0.0");
-
-            double direction = Math.pow((double)(-1.0), (double)(idx));
-            lon = lon + (direction * 0.00006);
-            System.out.println(lon);
-            
-            double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
-            Vector3Double location = espdu.getEntityLocation();
-            location.setX(disCoordinates[0]);
-            location.setY(disCoordinates[1]);
-            location.setZ(disCoordinates[2]);
-            System.out.println("lat, lon:" + lat + ", " + lon);
-            System.out.println("DIS coord:" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
-
-            // Optionally, we can do some rotation of the entity
-            /*
-            Orientation orientation = espdu.getEntityOrientation();
-            float psi = orientation.getPsi();
-            psi = psi + idx;
-            orientation.setPsi(psi);
-            orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
-             */
-            
-            // You can set other ESPDU values here, such as the velocity, acceleration,
-            // and so on.
-
-            // Marshal out the espdu object to a byte array, then send a datagram
-            // packet with that data in it.
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            DataOutputStream dos = new DataOutputStream(baos);
-            espdu.marshal(dos);
-
-            FirePdu fire = new FirePdu();
-            byte[] fireArray = fire.marshal();
-            
-            // The byte array here is the packet in DIS format. We put that into a 
-            // datagram and send it.
-            byte[] data = baos.toByteArray();
-
-            bcastAddresses = getBroadcastAddresses();
-            Iterator it = bcastAddresses.iterator();
-            while(it.hasNext())
-            {
-               InetAddress bcast = (InetAddress)it.next();
-               System.out.println("Sending bcast to " + bcast);
-               DatagramPacket packet = new DatagramPacket(data, data.length, bcast, 3000);
-               socket.send(packet);
-               packet = new DatagramPacket(fireArray, fireArray.length, bcast, 3000);
-               //socket.send(packet);
-            }
-            
-            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
-            Thread.sleep(3000);
-
-            location = espdu.getEntityLocation();
-            
-            System.out.println("Espdu #" + idx + " EID=[" + eid.getSite() + "," + eid.getApplication() + "," + eid.getEntity() + "]");
-            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
-            double c[] = {location.getX(), location.getY(), location.getZ()};
-            double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
-//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
-
-        }
-    }
-    catch(Exception e)
-    {
-        System.out.println(e);
-    }
-        
-}
-
- /**
-    * A number of sites get all snippy about using 255.255.255.255 for a bcast
-    * address; it trips their security software and they kick you off their 
-    * network. (Comcast, NPS.) This determines the bcast address for all
-    * connected interfaces, based on the IP and subnet mask. If you have
-    * a dual-homed host it will return a bcast address for both. If you have
-    * some VMs running on your host this will pick up the addresses for those
-    * as well--eg running VMWare on your laptop with a local IP this will
-    * also pick up a 192.168 address assigned to the VM by the host OS.
-    * 
-    * @return set of all bcast addresses
-    */
-   public static Set<InetAddress> getBroadcastAddresses()
-   {
-       Set<InetAddress> bcastAddresses = new HashSet<InetAddress>();
-       Enumeration interfaces;
-       
-       try
-       {
-           interfaces = NetworkInterface.getNetworkInterfaces();
-           
-           while(interfaces.hasMoreElements())
-           {
-               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
-               
-               if(anInterface.isUp())
-               {
-                   Iterator it = anInterface.getInterfaceAddresses().iterator();
-                   while(it.hasNext())
-                   {
-                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
-                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
-                           continue;
-                       
-                       //System.out.println("Getting bcast address for " + anAddress);
-                       InetAddress abcast = anAddress.getBroadcast();
-                       if(abcast != null)
-                        bcastAddresses.add(abcast);
-                   }
-               }
-           }
-           
-       }
-       catch(Exception e)
-       {
-           e.printStackTrace();
-           System.out.println(e);
-       }
-       
-       return bcastAddresses;   
-   }
-
-}
diff --git a/projects/Assignments/homework3/Angel_OpenDisEspduSender.java b/projects/Assignments/homework3/Angel_OpenDisEspduSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..100647dc1226e851771844b16475cb3e15ae8076
--- /dev/null
+++ b/projects/Assignments/homework3/Angel_OpenDisEspduSender.java
@@ -0,0 +1,341 @@
+//package edu.nps.moves.examples; // copy example from OpenDIS distribution, modify to serve as template
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import edu.nps.moves.dis.*;
+import edu.nps.moves.disutil.CoordinateConversions;
+import edu.nps.moves.disutil.DisTime;
+
+/**
+ * Creates and sends ESPDUs in IEEE binary format. 
+ *
+ * @author DMcG
+ */
+public class Angel_OpenDisEspduSender 
+{
+    public static final int NUMBER_TO_SEND = 5000;
+
+    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
+
+    /** Default multicast group address we send on */
+    public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
+   
+    /** Default port we send on */
+    public static final int    DIS_DESTINATION_PORT = 3000;
+    
+/** Possible system properties, passed in via -Dattr=val
+     * networkMode: unicast, broadcast, multicast
+     * destinationIp: where to send the packet. If in multicast mode, this can be multicast.
+     *                To determine broadcast destination IP, use an online broadcast address
+     *                calculator, for example http://www.remotemonitoringsystems.ca/broadcast.php
+     *                If in multicast mode, a join() will be done on the multicast address.
+     * port: port used for both source and destination.
+     * @param args 
+     */
+public static void main(String args[])
+{
+    /** an entity state pdu */
+    EntityStatePdu espdu = new EntityStatePdu();
+    MulticastSocket socket = null; // must be initialized, even if null
+    DisTime disTime = DisTime.getInstance(); // TODO explain
+    int alternator = -1;
+    
+    // ICBM coordinates for my office
+    double lat = 36.595517; 
+    double lon = -121.877000;
+    
+    // Default settings. These are used if no system properties are set. 
+    // If system properties are passed in, these are over ridden.
+    int port = DIS_DESTINATION_PORT;
+    NetworkMode mode = NetworkMode.BROADCAST;
+    InetAddress destinationIp = null; // must be initialized, even if null
+    
+    try
+    {
+        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
+    }
+    catch(UnknownHostException e)
+    {
+        System.out.println(e + " Cannot create multicast address");
+        System.exit(0);
+    }
+    
+    // All system properties, passed in on the command line via -Dattribute=value
+    Properties systemProperties = System.getProperties();
+    
+    // IP address we send to
+    String destinationIpString = systemProperties.getProperty("destinationIp");
+    
+    // Port we send to, and local port we open the socket on
+    String portString = systemProperties.getProperty("port");
+    
+    // Network mode: unicast, multicast, broadcast
+    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
+        
+    // Set up a socket to send information
+    try
+    {
+        // Port we send to
+        if(portString != null)
+            port = Integer.parseInt(portString);
+        
+        socket = new MulticastSocket(port);
+        
+        // Where we send packets to, the destination IP address
+        if(destinationIpString != null)
+        {
+            destinationIp = InetAddress.getByName(destinationIpString);
+        }
+
+        // Type of transport: unicast, broadcast, or multicast
+		// TODO convert to String constants
+        if(networkModeString != null)
+        {
+            if(networkModeString.equalsIgnoreCase("unicast"))
+                mode = NetworkMode.UNICAST;
+            else if(networkModeString.equalsIgnoreCase("broadcast"))
+                mode = NetworkMode.BROADCAST;
+            else if(networkModeString.equalsIgnoreCase("multicast"))
+            {
+                mode = NetworkMode.MULTICAST;
+                if(!destinationIp.isMulticastAddress())
+                {
+                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
+                }
+                
+                socket.joinGroup(destinationIp);
+            }
+        } // end networkModeString
+    }
+    catch(IOException | RuntimeException e)
+    {
+        System.out.println("Unable to initialize networking. Exiting.");
+        System.out.println(e);
+        System.exit(-1);
+    }
+    
+    // Initialize values in the Entity State PDU object. The exercise ID is 
+    // a way to differentiate between different virtual worlds on one network.
+    // Note that some values (such as the PDU type and PDU family) are set
+    // automatically when you create the ESPDU.
+    espdu.setExerciseID((short)1);
+    
+    // The EID is the unique identifier for objects in the world. This 
+    // EID should match up with the ID for the object specified in the 
+    // VMRL/x3d/virtual world.
+    EntityID entityID = espdu.getEntityID();
+    entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
+    entityID.setApplication(1); 
+    entityID.setEntity(2); 
+    
+    // Set the entity type. SISO has a big list of enumerations, so that by
+    // specifying various numbers we can say this is an M1A2 American tank,
+    // the USS Enterprise, and so on. We'll make this a tank. There is a 
+    // separate project elsehwhere in this project that implements DIS 
+    // enumerations in C++ and Java, but to keep things simple we just use
+    // numbers here.
+    EntityType entityType = espdu.getEntityType();
+    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
+    entityType.setCountry(225);              // USA
+    entityType.setDomain((short)2);          // AIR (vs air, surface, subsurface, space)
+    entityType.setCategory((short)2);        // Fighter/Attack
+    entityType.setSubcategory((short)2);     // M1 Abrams
+    entityType.setSpec((short)3);            // M1A2 Abrams
+    
+
+    Set<InetAddress> broadcastAddresses;
+    // Loop through sending N ESPDUs
+    try
+    {
+        System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
+            double disCoordinates1[] = CoordinateConversions.getXYZfromLatLonDegrees(36.593731, -121.882534, 1.0);
+            double disCoordinates2[] = CoordinateConversions.getXYZfromLatLonDegrees(36.594548, -121.882651, 1.0);
+            double disCoordinates3[] = CoordinateConversions.getXYZfromLatLonDegrees(36.596826, -121.882694, 1.0);
+            double disCoordinates4[] = CoordinateConversions.getXYZfromLatLonDegrees(36.598394, -121.883188, 1.0);
+            double disCoordinates5[] = CoordinateConversions.getXYZfromLatLonDegrees(36.599927, -121.883510, 1.0);
+            double disCoordinates6[] = CoordinateConversions.getXYZfromLatLonDegrees(36.599979, -121.887286, 1.0);
+            double disCoordinates7[] = CoordinateConversions.getXYZfromLatLonDegrees(36.598170, -121.887715, 1.0);
+            double disCoordinates8[] = CoordinateConversions.getXYZfromLatLonDegrees(36.596826, -121.888895, 1.0);
+            double disCoordinates9[] = CoordinateConversions.getXYZfromLatLonDegrees(36.595121, -121.889239, 1.0);
+            double disCoordinates10[] = CoordinateConversions.getXYZfromLatLonDegrees(36.594415,-121.885934, 1.0);
+            
+        double[][] disCoords = {disCoordinates1, disCoordinates2, disCoordinates3, disCoordinates4,
+            disCoordinates5, disCoordinates6, disCoordinates7, disCoordinates8, disCoordinates8, 
+            disCoordinates10};
+  
+        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
+        {
+            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
+            // hour, and time is set to DIS time units from the top of the hour. 
+            // This means that if you start sending just before the top of the hour
+            // the time units can roll over to zero as you are sending. The receivers
+            // (escpecially homegrown ones) are often not able to detect rollover
+            // and may start discarding packets as dupes or out of order. We use
+            // an NPS timestamp here, hundredths of a second since the start of the
+            // year. The DIS standard for time is often ignored in the wild; I've seen
+            // people use Unix time (seconds since 1970) and more. Or you can
+            // just stuff idx into the timestamp field to get something that is monotonically
+            // increasing.
+            
+            // Note that timestamp is used to detect duplicate and out of order packets. 
+            // That means if you DON'T change the timestamp, many implementations will simply
+            // discard subsequent packets that have an identical timestamp. Also, if they
+            // receive a PDU with an timestamp lower than the last one they received, they
+            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
+            // update the timestamp on ALL packets sent.
+            
+
+            // An alterative approach: actually follow the standard. It's a crazy concept,
+            // but it might just work.
+            int timestamp = disTime.getDisAbsoluteTimestamp();
+            espdu.setTimestamp(timestamp);
+            
+            // Set the position of the entity in the world. DIS uses a cartesian 
+            // coordinate system with the origin at the center of the earth, the x
+            // axis out at the equator and prime meridian, y out at the equator and
+            // 90 deg east, and z up and out the north pole. To place an object on
+            // the earth's surface you also need a model for the shape of the earth
+            // (it's not a sphere.) All the fancy math necessary to do this is in
+            // the SEDRIS SRM package. There are also some one-off formulas for 
+            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
+            // Here we use those one-off formulas.
+
+            // Modify the position of the object. This will send the object a little
+            // due east by adding some to the longitude every iteration. Since we
+            // are on the Pacific coast, this sends the object east. Assume we are
+            // at zero altitude. In other worlds you'd use DTED to determine the
+            // local ground altitude at that lat/lon, or you'd just use ground clamping.
+            // The x and y values will change, but the z value should not.
+            
+            //lon = lon + (double)((double)idx / 100000.0);
+            //System.out.println("lla=" + lat + "," + lon + ", 0.0");
+
+
+            //double direction = Math.pow((double)(-1.0), (double)(idx));
+            //lon = lon + (direction * 0.00006);
+            //System.out.println(lon);
+            
+
+
+            Vector3Double location = espdu.getEntityLocation();
+            int res = idx/2 % 10;
+            location.setX(disCoords[res][0]);
+            location.setY(disCoords[res][1]);
+            location.setZ(disCoords[res][2]);
+            //System.out.println("lat, lon:" + lat + ", " + lon);
+            //System.out.println("DIS coord:" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
+
+            // Optionally, we can do some rotation of the entity
+            /*
+            Orientation orientation = espdu.getEntityOrientation();
+            float psi = orientation.getPsi();
+            psi = psi + idx;
+            orientation.setPsi(psi);
+            orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
+             */
+            
+            // You can set other ESPDU values here, such as the velocity, acceleration,
+            // and so on.
+
+            // Marshal out the espdu object to a byte array, then send a datagram
+            // packet with that data in it.
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            DataOutputStream dos = new DataOutputStream(baos);
+            espdu.marshal(dos);
+
+            
+            //FirePdu fire = new FirePdu();
+            //byte[] fireArray = fire.marshal();
+            
+            // The byte array here is the packet in DIS format. We put that into a 
+            // datagram and send it.
+            byte[] data = baos.toByteArray();
+
+            broadcastAddresses = getBroadcastAddresses();
+            Iterator it = broadcastAddresses.iterator();
+            while(it.hasNext())
+            {
+               InetAddress broadcast = (InetAddress)it.next();
+               System.out.println("Sending broadcast datagram packet to " + broadcast);
+               DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, 3000);
+               socket.send(packet);
+			   // TODO experiment with these!  8)
+               //packet = new DatagramPacket(fireArray, fireArray.length, broadcast, 3000); // alternate
+               socket.send(packet);
+            }
+            
+            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
+            Thread.sleep(3000);
+
+            location = espdu.getEntityLocation();
+            
+            System.out.println("Espdu #" + idx + " EID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
+            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
+            double c[] = {location.getX(), location.getY(), location.getZ()};
+            double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
+//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
+
+        }
+    }
+    catch(IOException | InterruptedException e)
+    {
+        System.out.println(e);
+    }
+        
+}
+
+ /**
+    * A number of sites get all snippy about using 255.255.255.255 for a broadcast
+    * address; it trips their security software and they kick you off their 
+    * network. (Comcast, NPS.) This determines the broadcast address for all
+    * connected interfaces, based on the IP and subnet mask. If you have
+    * a dual-homed host it will return a broadcast address for both. If you have
+    * some VMs running on your host this will pick up the addresses for those
+    * as well--eg running VMWare on your laptop with a local IP this will
+    * also pick up a 192.168 address assigned to the VM by the host OS.
+    * 
+    * @return set of all broadcast addresses
+    */
+   public static Set<InetAddress> getBroadcastAddresses()
+   {
+       Set<InetAddress> broadcastAddresses = new HashSet<>();
+       Enumeration interfaces;
+       
+       try
+       {
+           interfaces = NetworkInterface.getNetworkInterfaces();
+           
+           while(interfaces.hasMoreElements())
+           {
+               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
+               
+               if(anInterface.isUp())
+               {
+                   Iterator it = anInterface.getInterfaceAddresses().iterator();
+                   while(it.hasNext())
+                   {
+                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
+                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
+                           continue;
+                       
+                       //System.out.println("Getting broadcast address for " + anAddress);
+                       InetAddress broadcastAddress = anAddress.getBroadcast();
+                       if(broadcastAddress != null)
+                          broadcastAddresses.add(broadcastAddress);
+                   }
+               }
+           }
+           
+       }
+       catch(SocketException e)
+       {
+           e.printStackTrace();
+           System.out.println(e);
+       }
+       
+       return broadcastAddresses;   
+   }
+
+}
diff --git a/projects/Assignments/homework3/AngelopoulosREADME.md b/projects/Assignments/homework3/AngelopoulosREADME.md
new file mode 100644
index 0000000000000000000000000000000000000000..bf6e056dcfd35700eaedff6ff73b6c0b6e43d41a
--- /dev/null
+++ b/projects/Assignments/homework3/AngelopoulosREADME.md
@@ -0,0 +1,34 @@
+## Homework Assignment 3 Checklist
+
+1. [x] Add X3D-Edit as Netbeans Plugin from https://savage.nps.edu/X3D-Edit/#Downloads
+
+1. [x] Optional: checkout Open-DIS-Java library source from https://github.com/open-dis/open-dis-java
+
+1. [x] Otherwise just inspect files of interest from
+   [edu.nps.moves.examples](https://github.com/open-dis/open-dis-java/tree/master/src/main/java/edu/nps/moves/examples)
+
+1. [x] Copy README.md and create YournameREADME.md documentation file...
+
+1. [x] Plan a track of interest, described in YournameREADME.md documentation file...
+
+The armor (Enhanced Ground Combat Vehicle) travels from intersection of Freemont and 68, down Camino Aguajito,
+left on Del Monte Ave, Left on Camino El Estero, and finally a left on Fremont to the beginning.  The travel movement is 
+roughly 1/3 of a mile every 24 seconds.  It might be a bit fast....but its ARMY/MARINE Strong!
+
+1. [x] Copy, then Refactor/Rename example file OpenDisEspduSender.java or OpenDisPduSender.java as YourNameSomething.java
+
+1. [x] Modify your example file to produce track PDUs (and be cool)
+
+1. [x] Generate PDUs...
+
+1. [x] Test PDU reading using Wireshark...
+
+Some examples of PDUs within WireShark
+
+111	32.870689	172.20.144.243	172.20.159.255	DIS	186	PDUType: 1 	 Entity State, Platform, Air, (1:1:2)
+110	32.870603	172.20.144.243	172.20.159.255	DIS	186	PDUType: 1 	 Entity State, Platform, Air, (1:1:2)
+97	29.761150	172.20.144.243	172.20.159.255	DIS	186	PDUType: 1 	 Entity State, Platform, Air, (1:1:2)
+
+1. [x] Record PDU file using X3D-Edit...
+
+1. [x] Playback PDU file using X3D-Edit...
diff --git a/projects/Assignments/homework3/Angelopoulos_dispackets.disbin b/projects/Assignments/homework3/Angelopoulos_dispackets.disbin
new file mode 100644
index 0000000000000000000000000000000000000000..75f5caf1ddc7fed9a2c5ac6d83bc52d1e4fa1337
Binary files /dev/null and b/projects/Assignments/homework3/Angelopoulos_dispackets.disbin differ
diff --git a/projects/Assignments/homework3/Angelopoulos_dispackets.disbin.disbinidx b/projects/Assignments/homework3/Angelopoulos_dispackets.disbin.disbinidx
new file mode 100644
index 0000000000000000000000000000000000000000..159aa2e788491aa6a444ff345031cbd29ecc337c
Binary files /dev/null and b/projects/Assignments/homework3/Angelopoulos_dispackets.disbin.disbinidx differ
diff --git a/projects/Assignments/homework3/BlankenbekerDISpacketsHW3.disbin b/projects/Assignments/homework3/BlankenbekerDISpacketsHW3.disbin
new file mode 100644
index 0000000000000000000000000000000000000000..8dc1bd8f7790381bfa99bfd65342bf48ee6e65dd
Binary files /dev/null and b/projects/Assignments/homework3/BlankenbekerDISpacketsHW3.disbin differ
diff --git a/projects/Assignments/homework3/BlankenbekerDISpacketsHW3.disbin.disbinidx b/projects/Assignments/homework3/BlankenbekerDISpacketsHW3.disbin.disbinidx
new file mode 100644
index 0000000000000000000000000000000000000000..5ed6ff1e1123af2dd04e7e9c8247aa60ad6c0f66
Binary files /dev/null and b/projects/Assignments/homework3/BlankenbekerDISpacketsHW3.disbin.disbinidx differ
diff --git a/projects/Assignments/homework3/BlankenbekerHW3README.md b/projects/Assignments/homework3/BlankenbekerHW3README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c77377b79cd3818957b32fab44892fd2da0f1ec0
--- /dev/null
+++ b/projects/Assignments/homework3/BlankenbekerHW3README.md
@@ -0,0 +1,30 @@
+## Homework Assignment 3 Checklist
+
+1. [x] Add X3D-Edit as Netbeans Plugin from https://savage.nps.edu/X3D-Edit/#Downloads
+
+1. [x] Optional: checkout Open-DIS-Java library source from https://github.com/open-dis/open-dis-java
+
+1. [x] Otherwise just inspect files of interest from
+   [edu.nps.moves.examples](https://github.com/open-dis/open-dis-java/tree/master/src/main/java/edu/nps/moves/examples)
+
+1. [X] Copy README.md and create YournameREADME.md documentation file...
+
+1. [x] Plan a track of interest, described in YournameREADME.md documentation file...
+
+    The track consists of a highway driving route from Monterey, CA to Palmdale, CA.
+
+1. [x] Copy, then Refactor/Rename example file OpenDisEspduSender.java or OpenDisPduSender.java as YourNameSomething.java
+
+1. [x] Modify your example file to produce track PDUs (and be cool)
+
+1. [x] Generate PDUs...
+
+1. [x] Test PDU reading using Wireshark...
+    
+    Wireshark output depicted activity when PDUs were being created.
+
+1. [x] Record PDU file using X3D-Edit...
+
+1. [x] Playback PDU file using X3D-Edit...
+
+PDU file succesfully recorded and played back using the X3D-Edit tools.
diff --git a/projects/Assignments/homework3/AngelBlank/ABEspduSenderA.java b/projects/Assignments/homework3/BlankenbekerOpenDisEspduSender.java
similarity index 72%
rename from projects/Assignments/homework3/AngelBlank/ABEspduSenderA.java
rename to projects/Assignments/homework3/BlankenbekerOpenDisEspduSender.java
index 4a6391b7681db3fb44248bfaa2bb652298b00ca8..5fdfd87a4b6834e2fb81442ffa761383d58c50d7 100644
--- a/projects/Assignments/homework3/AngelBlank/ABEspduSenderA.java
+++ b/projects/Assignments/homework3/BlankenbekerOpenDisEspduSender.java
@@ -1,324 +1,364 @@
-package AngelBlank;
-
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import edu.nps.moves.dis.*;
-import edu.nps.moves.disutil.CoordinateConversions;
-import edu.nps.moves.disutil.DisTime;
-
-/**
- * Creates and sends ESPDUs in IEEE binary format. 
- *
- * @author DMcG
- */
-public class ABEspduSenderA 
-{
-    public static final int NUMBER_TO_SEND = 5000;
-
-    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
-
-    /** default multicast group we send on */
-    public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
-   
-    /** Port we send on */
-    public static final int    DIS_DESTINATION_PORT = 3000;
-    
-/** Possible system properties, passed in via -Dattr=val
-     * networkMode: unicast, broadcast, multicast
-     * destinationIp: where to send the packet. If in multicast mode, this can be mcast.
-     *                To determine bcast destination IP, use an online bcast address
-     *                caclulator, for example http://www.remotemonitoringsystems.ca/broadcast.php
-     *                If in mcast mode, a join() will be done on the mcast address.
-     * port: port used for both source and destination.
-     * @param args 
-     */
-public static void main(String args[])
-{
-    /** an entity state pdu */
-    EntityStatePdu espdu = new EntityStatePdu();
-    MulticastSocket socket = null;
-    DisTime disTime = DisTime.getInstance();
-    int alternator = -1;
-    
-    // ICBM coordinates for my office
-    double lat = 36.595517; 
-    double lon = -121.877000;
-
-    
-    // Default settings. These are used if no system properties are set. 
-    // If system properties are passed in, these are over ridden.
-    int port = DIS_DESTINATION_PORT;
-    NetworkMode mode = NetworkMode.MULTICAST;
-    InetAddress destinationIp = null;
-    
-    try
-    {
-        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
-    }
-    catch(Exception e)
-    {
-        System.out.println(e + " Cannot create multicast address");
-        System.exit(0);
-    }
-    
-    // All system properties, passed in on the command line via -Dattribute=value
-    Properties systemProperties = System.getProperties();
-    
-    // IP address we send to
-    String destinationIpString = systemProperties.getProperty("destinationIp");
-    
-    // Port we send to, and local port we open the socket on
-    String portString = systemProperties.getProperty("port");
-    
-    // Network mode: unicast, multicast, broadcast
-    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
-        
-
-    // Set up a socket to send information
-    try
-    {
-        // Port we send to
-        if(portString != null)
-            port = Integer.parseInt(portString);
-        
-        socket = new MulticastSocket(port);
-        
-        // Where we send packets to, the destination IP address
-        if(destinationIpString != null)
-        {
-            destinationIp = InetAddress.getByName(destinationIpString);
-        }
-
-        // Type of transport: unicast, broadcast, or multicast
-        if(networkModeString != null)
-        {
-            if(networkModeString.equalsIgnoreCase("unicast"))
-                mode = NetworkMode.UNICAST;
-            else if(networkModeString.equalsIgnoreCase("broadcast"))
-                mode = NetworkMode.BROADCAST;
-            else if(networkModeString.equalsIgnoreCase("multicast"))
-            {
-                mode = NetworkMode.MULTICAST;
-                if(!destinationIp.isMulticastAddress())
-                {
-                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
-                }
-                
-                socket.joinGroup(destinationIp);
-                
-            }
-        } // end networkModeString
-    }
-    catch(Exception e)
-    {
-        System.out.println("Unable to initialize networking. Exiting.");
-        System.out.println(e);
-        System.exit(-1);
-    }
-    
-    // Initialize values in the Entity State PDU object. The exercise ID is 
-    // a way to differentiate between different virtual worlds on one network.
-    // Note that some values (such as the PDU type and PDU family) are set
-    // automatically when you create the ESPDU.
-    espdu.setExerciseID((short)1);
-    
-    // The EID is the unique identifier for objects in the world. This 
-    // EID should match up with the ID for the object specified in the 
-    // VMRL/x3d/virtual world.
-    EntityID eid = espdu.getEntityID();
-    eid.setSite(1);  // 0 is apparently not a valid site number, per the spec
-    eid.setApplication(1); 
-    eid.setEntity(2); 
-    
-    // Set the entity type. SISO has a big list of enumerations, so that by
-    // specifying various numbers we can say this is an M1A2 American tank,
-    // the USS Enterprise, and so on. We'll make this a tank. There is a 
-    // separate project elsehwhere in this project that implements DIS 
-    // enumerations in C++ and Java, but to keep things simple we just use
-    // numbers here.
-    EntityType entityType = espdu.getEntityType();
-    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
-    entityType.setCountry(225);              // USA
-    entityType.setDomain((short)1);          // Land (vs air, surface, subsurface, space)
-    entityType.setCategory((short)1);        // Tank
-    entityType.setSubcategory((short)1);     // M1 Abrams
-    entityType.setSpec((short)3);            // M1A2 Abrams
-    
-
-    Set<InetAddress> bcastAddresses = getBroadcastAddresses();
-    // Loop through sending N ESPDUs
-    try
-    {
-        System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
-        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
-        {
-            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
-            // hour, and time is set to DIS time units from the top of the hour. 
-            // This means that if you start sending just before the top of the hour
-            // the time units can roll over to zero as you are sending. The receivers
-            // (escpecially homegrown ones) are often not able to detect rollover
-            // and may start discarding packets as dupes or out of order. We use
-            // an NPS timestamp here, hundredths of a second since the start of the
-            // year. The DIS standard for time is often ignored in the wild; I've seen
-            // people use Unix time (seconds since 1970) and more. Or you can
-            // just stuff idx into the timestamp field to get something that is monotonically
-            // increasing.
-            
-            // Note that timestamp is used to detect duplicate and out of order packets. 
-            // That means if you DON'T change the timestamp, many implementations will simply
-            // discard subsequent packets that have an identical timestamp. Also, if they
-            // receive a PDU with an timestamp lower than the last one they received, they
-            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
-            // update the timestamp on ALL packets sent.
-            
-
-            // An alterative approach: actually follow the standard. It's a crazy concept,
-            // but it might just work.
-            int ts = disTime.getDisAbsoluteTimestamp();
-            espdu.setTimestamp(ts);
-            
-            // Set the position of the entity in the world. DIS uses a cartesian 
-            // coordinate system with the origin at the center of the earth, the x
-            // axis out at the equator and prime meridian, y out at the equator and
-            // 90 deg east, and z up and out the north pole. To place an object on
-            // the earth's surface you also need a model for the shape of the earth
-            // (it's not a sphere.) All the fancy math necessary to do this is in
-            // the SEDRIS SRM package. There are also some one-off formulas for 
-            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
-            // Here we use those one-off formulas.
-
-            // Modify the position of the object. This will send the object a little
-            // due east by adding some to the longitude every iteration. Since we
-            // are on the Pacific coast, this sends the object east. Assume we are
-            // at zero altitude. In other worlds you'd use DTED to determine the
-            // local ground altitude at that lat/lon, or you'd just use ground clamping.
-            // The x and y values will change, but the z value should not.
-            
-            //lon = lon + (double)((double)idx / 100000.0);
-            //System.out.println("lla=" + lat + "," + lon + ", 0.0");
-
-            double direction = Math.pow((double)(-1.0), (double)(idx));
-            lon = lon + (direction * 0.00006);
-            System.out.println(lon);
-            
-            double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
-            Vector3Double location = espdu.getEntityLocation();
-            location.setX(disCoordinates[0]);
-            location.setY(disCoordinates[1]);
-            location.setZ(disCoordinates[2]);
-            System.out.println("lat, lon:" + lat + ", " + lon);
-            System.out.println("DIS coord:" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
-
-            // Optionally, we can do some rotation of the entity
-            /*
-            Orientation orientation = espdu.getEntityOrientation();
-            float psi = orientation.getPsi();
-            psi = psi + idx;
-            orientation.setPsi(psi);
-            orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
-             */
-            
-            // You can set other ESPDU values here, such as the velocity, acceleration,
-            // and so on.
-
-            // Marshal out the espdu object to a byte array, then send a datagram
-            // packet with that data in it.
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            DataOutputStream dos = new DataOutputStream(baos);
-            espdu.marshal(dos);
-
-            FirePdu fire = new FirePdu();
-            byte[] fireArray = fire.marshal();
-            
-            // The byte array here is the packet in DIS format. We put that into a 
-            // datagram and send it.
-            byte[] data = baos.toByteArray();
-
-            bcastAddresses = getBroadcastAddresses();
-            Iterator it = bcastAddresses.iterator();
-            while(it.hasNext())
-            {
-               InetAddress bcast = (InetAddress)it.next();
-               System.out.println("Sending bcast to " + bcast);
-               DatagramPacket packet = new DatagramPacket(data, data.length, bcast, 3000);
-               socket.send(packet);
-               packet = new DatagramPacket(fireArray, fireArray.length, bcast, 3000);
-               //socket.send(packet);
-            }
-            
-            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
-            Thread.sleep(3000);
-
-            location = espdu.getEntityLocation();
-            
-            System.out.println("Espdu #" + idx + " EID=[" + eid.getSite() + "," + eid.getApplication() + "," + eid.getEntity() + "]");
-            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
-            double c[] = {location.getX(), location.getY(), location.getZ()};
-            double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
-//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
-
-        }
-    }
-    catch(Exception e)
-    {
-        System.out.println(e);
-    }
-        
-}
-
- /**
-    * A number of sites get all snippy about using 255.255.255.255 for a bcast
-    * address; it trips their security software and they kick you off their 
-    * network. (Comcast, NPS.) This determines the bcast address for all
-    * connected interfaces, based on the IP and subnet mask. If you have
-    * a dual-homed host it will return a bcast address for both. If you have
-    * some VMs running on your host this will pick up the addresses for those
-    * as well--eg running VMWare on your laptop with a local IP this will
-    * also pick up a 192.168 address assigned to the VM by the host OS.
-    * 
-    * @return set of all bcast addresses
-    */
-   public static Set<InetAddress> getBroadcastAddresses()
-   {
-       Set<InetAddress> bcastAddresses = new HashSet<InetAddress>();
-       Enumeration interfaces;
-       
-       try
-       {
-           interfaces = NetworkInterface.getNetworkInterfaces();
-           
-           while(interfaces.hasMoreElements())
-           {
-               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
-               
-               if(anInterface.isUp())
-               {
-                   Iterator it = anInterface.getInterfaceAddresses().iterator();
-                   while(it.hasNext())
-                   {
-                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
-                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
-                           continue;
-                       
-                       //System.out.println("Getting bcast address for " + anAddress);
-                       InetAddress abcast = anAddress.getBroadcast();
-                       if(abcast != null)
-                        bcastAddresses.add(abcast);
-                   }
-               }
-           }
-           
-       }
-       catch(Exception e)
-       {
-           e.printStackTrace();
-           System.out.println(e);
-       }
-       
-       return bcastAddresses;   
-   }
-
-}
+// package edu.nps.moves.examples; // copy example from OpenDIS distribution, modify to serve as template
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import edu.nps.moves.dis.*;
+import edu.nps.moves.disutil.CoordinateConversions;
+import edu.nps.moves.disutil.DisTime;
+
+/**
+ * Creates and sends ESPDUs in IEEE binary format. 
+ *
+ * @author DMcG
+ */
+public class BlankenbekerOpenDisEspduSender 
+{
+    
+    public static final int NUMBER_TO_SEND = 5000;
+
+    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
+
+    /** Default multicast group address we send on */
+    public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
+    
+    private static final ArrayList <Float[]> track = new ArrayList<>();
+   
+    /** Default port we send on */
+    public static final int    DIS_DESTINATION_PORT = 3000;
+    
+/** Possible system properties, passed in via -Dattr=val
+     * networkMode: unicast, broadcast, multicast
+     * destinationIp: where to send the packet. If in multicast mode, this can be multicast.
+     *                To determine broadcast destination IP, use an online broadcast address
+     *                calculator, for example http://www.remotemonitoringsystems.ca/broadcast.php
+     *                If in multicast mode, a join() will be done on the multicast address.
+     * port: port used for both source and destination.
+     * @param args 
+     */
+public static void main(String args[])
+{
+    /** an entity state pdu */
+    EntityStatePdu espdu = new EntityStatePdu();
+    MulticastSocket socket = null; // must be initialized, even if null
+    DisTime disTime = DisTime.getInstance(); // TODO explain
+    int alternator = -1;
+    
+    // ICBM coordinates for my office
+    //double lat = 36.595517; 
+    //double lon = -121.877000;
+    
+    // Default settings. These are used if no system properties are set. 
+    // If system properties are passed in, these are over ridden.
+    int port = DIS_DESTINATION_PORT;
+    NetworkMode mode = NetworkMode.MULTICAST;
+    InetAddress destinationIp = null; // must be initialized, even if null
+    
+    try
+    {
+        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
+    }
+    catch(UnknownHostException e)
+    {
+        System.out.println(e + " Cannot create multicast address");
+        System.exit(0);
+    }
+    
+    // All system properties, passed in on the command line via -Dattribute=value
+    Properties systemProperties = System.getProperties();
+    
+    // IP address we send to
+    String destinationIpString = systemProperties.getProperty("destinationIp");
+    
+    // Port we send to, and local port we open the socket on
+    String portString = systemProperties.getProperty("port");
+    
+    // Network mode: unicast, multicast, broadcast
+    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
+        
+    // Set up a socket to send information
+    try
+    {
+        // Port we send to
+        if(portString != null)
+            port = Integer.parseInt(portString);
+        
+        socket = new MulticastSocket(port);
+        
+        // Where we send packets to, the destination IP address
+        if(destinationIpString != null)
+        {
+            destinationIp = InetAddress.getByName(destinationIpString);
+        }
+
+        // Type of transport: unicast, broadcast, or multicast
+		// TODO convert to String constants
+        if(networkModeString != null)
+        {
+            if(networkModeString.equalsIgnoreCase("unicast"))
+                mode = NetworkMode.UNICAST;
+            else if(networkModeString.equalsIgnoreCase("broadcast"))
+                mode = NetworkMode.BROADCAST;
+            else if(networkModeString.equalsIgnoreCase("multicast"))
+            {
+                mode = NetworkMode.MULTICAST;
+                if(!destinationIp.isMulticastAddress())
+                {
+                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
+                }
+                
+                socket.joinGroup(destinationIp);
+            }
+        } // end networkModeString
+    }
+    catch(IOException | RuntimeException e)
+    {
+        System.out.println("Unable to initialize networking. Exiting.");
+        System.out.println(e);
+        System.exit(-1);
+    }
+    
+    // Initialize values in the Entity State PDU object. The exercise ID is 
+    // a way to differentiate between different virtual worlds on one network.
+    // Note that some values (such as the PDU type and PDU family) are set
+    // automatically when you create the ESPDU.
+    espdu.setExerciseID((short)1);
+    
+    // The EID is the unique identifier for objects in the world. This 
+    // EID should match up with the ID for the object specified in the 
+    // VMRL/x3d/virtual world.
+    EntityID entityID = espdu.getEntityID();
+    entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
+    entityID.setApplication(1); 
+    entityID.setEntity(2); 
+    
+    // Set the entity type. SISO has a big list of enumerations, so that by
+    // specifying various numbers we can say this is an M1A2 American tank,
+    // the USS Enterprise, and so on. We'll make this a tank. There is a 
+    // separate project elsehwhere in this project that implements DIS 
+    // enumerations in C++ and Java, but to keep things simple we just use
+    // numbers here.
+    EntityType entityType = espdu.getEntityType();
+    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
+    entityType.setCountry(225);              // USA
+    entityType.setDomain((short)1);          // Land (vs air, surface, subsurface, space)
+    entityType.setCategory((short)1);        // Tank
+    entityType.setSubcategory((short)1);     // M1 Abrams
+    entityType.setSpec((short)3);            // M1A2 Abrams
+    
+
+    Set<InetAddress> broadcastAddresses;
+    // Loop through sending N ESPDUs
+    try
+    {
+        
+        Float[] TrackCoor1 = new Float [2];
+        TrackCoor1[0] = 36.59135f;
+        TrackCoor1[1] = -121.88051f;
+        track.add(TrackCoor1);
+        Float[] TrackCoor2 = new Float [2];
+        TrackCoor2[0] = 36.59487f;
+        TrackCoor2[1] = -121.86739f;
+        track.add(TrackCoor2);
+        Float[] TrackCoor3 = new Float [2];
+        TrackCoor3[0] = 36.63259f;
+        TrackCoor3[1] = -121.66926f;
+        track.add(TrackCoor3);
+        Float[] TrackCoor4 = new Float [2];
+        TrackCoor4[0] = 36.64481f;
+        TrackCoor4[1] = -121.61162f;
+        track.add(TrackCoor4);
+        Float[] TrackCoor5 = new Float [2];
+        TrackCoor5[0] = 35.64239f;
+        TrackCoor5[1] = -120.68503f;
+        track.add(TrackCoor5);
+        Float[] TrackCoor6 = new Float [2];
+        TrackCoor6[0] = 35.61577f;
+        TrackCoor6[1] = -119.65283f;
+        track.add(TrackCoor6);
+        Float[] TrackCoor7 = new Float [2];
+        TrackCoor7[0] = 34.76589f;
+        TrackCoor7[1] = -118.79854f;
+        track.add(TrackCoor7);
+        Float[] TrackCoor8 = new Float [2];
+        TrackCoor8[0] = 34.77651f;
+        TrackCoor8[1] = -118.17049f;
+        track.add(TrackCoor8);
+        Float[] TrackCoor9 = new Float [2];
+        TrackCoor9[0] = 34.5806f;
+        TrackCoor9[1] = -118.1334f;
+        track.add(TrackCoor9);
+        
+//        System.out.println("********" + String.valueOf(track_coordinates[0]) );
+//        System.out.println("********" + track_coordinates.get(5)[1]);
+        System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
+        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
+        {
+            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
+            // hour, and time is set to DIS time units from the top of the hour. 
+            // This means that if you start sending just before the top of the hour
+            // the time units can roll over to zero as you are sending. The receivers
+            // (escpecially homegrown ones) are often not able to detect rollover
+            // and may start discarding packets as dupes or out of order. We use
+            // an NPS timestamp here, hundredths of a second since the start of the
+            // year. The DIS standard for time is often ignored in the wild; I've seen
+            // people use Unix time (seconds since 1970) and more. Or you can
+            // just stuff idx into the timestamp field to get something that is monotonically
+            // increasing.
+            
+            // Note that timestamp is used to detect duplicate and out of order packets. 
+            // That means if you DON'T change the timestamp, many implementations will simply
+            // discard subsequent packets that have an identical timestamp. Also, if they
+            // receive a PDU with an timestamp lower than the last one they received, they
+            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
+            // update the timestamp on ALL packets sent.
+            
+
+            // An alterative approach: actually follow the standard. It's a crazy concept,
+            // but it might just work.
+            int timestamp = disTime.getDisAbsoluteTimestamp();
+            espdu.setTimestamp(timestamp);
+            
+            // Set the position of the entity in the world. DIS uses a cartesian 
+            // coordinate system with the origin at the center of the earth, the x
+            // axis out at the equator and prime meridian, y out at the equator and
+            // 90 deg east, and z up and out the north pole. To place an object on
+            // the earth's surface you also need a model for the shape of the earth
+            // (it's not a sphere.) All the fancy math necessary to do this is in
+            // the SEDRIS SRM package. There are also some one-off formulas for 
+            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
+            // Here we use those one-off formulas.
+
+            // Modify the position of the object. This will send the object a little
+            // due east by adding some to the longitude every iteration. Since we
+            // are on the Pacific coast, this sends the object east. Assume we are
+            // at zero altitude. In other worlds you'd use DTED to determine the
+            // local ground altitude at that lat/lon, or you'd just use ground clamping.
+            // The x and y values will change, but the z value should not.
+            
+            //lon = lon + (double)((double)idx / 100000.0);
+            //System.out.println("lla=" + lat + "," + lon + ", 0.0");
+
+            Float lat = track.get(idx)[0];
+            Float lon = track.get(idx)[1];
+            
+            double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
+            Vector3Double location = espdu.getEntityLocation();
+            location.setX(disCoordinates[0]);
+            location.setY(disCoordinates[1]);
+            location.setZ(disCoordinates[2]);
+            System.out.println("lat, lon:" + lat + ", " + lon);
+            System.out.println("DIS coord:" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
+
+            // Optionally, we can do some rotation of the entity
+            /*
+            Orientation orientation = espdu.getEntityOrientation();
+            float psi = orientation.getPsi();
+            psi = psi + idx;
+            orientation.setPsi(psi);
+            orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
+             */
+            
+            // You can set other ESPDU values here, such as the velocity, acceleration,
+            // and so on.
+
+            // Marshal out the espdu object to a byte array, then send a datagram
+            // packet with that data in it.
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            DataOutputStream dos = new DataOutputStream(baos);
+            espdu.marshal(dos);
+
+            FirePdu fire = new FirePdu();
+            byte[] fireArray = fire.marshal();
+            
+            // The byte array here is the packet in DIS format. We put that into a 
+            // datagram and send it.
+            byte[] data = baos.toByteArray();
+
+            broadcastAddresses = getBroadcastAddresses();
+            Iterator it = broadcastAddresses.iterator();
+            while(it.hasNext())
+            {
+               InetAddress broadcast = (InetAddress)it.next();
+               System.out.println("Sending broadcast datagram packet to " + broadcast);
+               DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, 3000);
+               socket.send(packet);
+			   // TODO experiment with these!  8)
+               packet = new DatagramPacket(fireArray, fireArray.length, broadcast, 3000); // alternate
+               socket.send(packet);
+            }
+            
+            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
+            Thread.sleep(3000);
+
+            location = espdu.getEntityLocation();
+            
+            System.out.println("Espdu #" + idx + " EID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
+            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
+            double c[] = {location.getX(), location.getY(), location.getZ()};
+            double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
+//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
+
+        }
+    }
+    catch(IOException | InterruptedException e)
+    {
+        System.out.println(e);
+    }
+        
+}
+
+ /**
+    * A number of sites get all snippy about using 255.255.255.255 for a broadcast
+    * address; it trips their security software and they kick you off their 
+    * network. (Comcast, NPS.) This determines the broadcast address for all
+    * connected interfaces, based on the IP and subnet mask. If you have
+    * a dual-homed host it will return a broadcast address for both. If you have
+    * some VMs running on your host this will pick up the addresses for those
+    * as well--eg running VMWare on your laptop with a local IP this will
+    * also pick up a 192.168 address assigned to the VM by the host OS.
+    * 
+    * @return set of all broadcast addresses
+    */
+   public static Set<InetAddress> getBroadcastAddresses()
+   {
+       Set<InetAddress> broadcastAddresses = new HashSet<>();
+       Enumeration interfaces;
+       
+       try
+       {
+           interfaces = NetworkInterface.getNetworkInterfaces();
+           
+           while(interfaces.hasMoreElements())
+           {
+               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
+               
+               if(anInterface.isUp())
+               {
+                   Iterator it = anInterface.getInterfaceAddresses().iterator();
+                   while(it.hasNext())
+                   {
+                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
+                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
+                           continue;
+                       
+                       //System.out.println("Getting broadcast address for " + anAddress);
+                       InetAddress broadcastAddress = anAddress.getBroadcast();
+                       if(broadcastAddress != null)
+                          broadcastAddresses.add(broadcastAddress);
+                   }
+               }
+           }
+           
+       }
+       catch(SocketException e)
+       {
+           e.printStackTrace();
+           System.out.println(e);
+       }
+       
+       return broadcastAddresses;   
+   }
+
+}
diff --git a/projects/Assignments/AngelBlankFP/EspduSenderB.java b/projects/Assignments/homework3/ConardSnellOpenDisEspduSender.java
similarity index 79%
rename from projects/Assignments/AngelBlankFP/EspduSenderB.java
rename to projects/Assignments/homework3/ConardSnellOpenDisEspduSender.java
index 80c46213cf5a45176f3ef35307259118c5bd5f9b..77612f87f13c33a13bcb7f03d6ddfd229b5a7dda 100644
--- a/projects/Assignments/AngelBlankFP/EspduSenderB.java
+++ b/projects/Assignments/homework3/ConardSnellOpenDisEspduSender.java
@@ -1,323 +1,324 @@
-package java.edu.nps.moves.examples;
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import edu.nps.moves.dis.*;
-import edu.nps.moves.disutil.CoordinateConversions;
-import edu.nps.moves.disutil.DisTime;
-
-/**
- * Creates and sends ESPDUs in IEEE binary format. 
- *
- * @author DMcG
- */
-public class EspduSenderB 
-{
-    public static final int NUMBER_TO_SEND = 5000;
-
-    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
-
-    /** default multicast group we send on */
-    public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
-   
-    /** Port we send on */
-    public static final int    DIS_DESTINATION_PORT = 3000;
-    
-/** Possible system properties, passed in via -Dattr=val
-     * networkMode: unicast, broadcast, multicast
-     * destinationIp: where to send the packet. If in multicast mode, this can be mcast.
-     *                To determine bcast destination IP, use an online bcast address
-     *                caclulator, for example http://www.remotemonitoringsystems.ca/broadcast.php
-     *                If in mcast mode, a join() will be done on the mcast address.
-     * port: port used for both source and destination.
-     * @param args 
-     */
-public static void main(String args[])
-{
-    /** an entity state pdu */
-    EntityStatePdu espdu = new EntityStatePdu();
-    MulticastSocket socket = null;
-    DisTime disTime = DisTime.getInstance();
-    int alternator = -1;
-    
-    // ICBM coordinates for my office
-    double lat = 36.595517; 
-    double lon = -121.877000;
-
-    
-    // Default settings. These are used if no system properties are set. 
-    // If system properties are passed in, these are over ridden.
-    int port = DIS_DESTINATION_PORT;
-    NetworkMode mode = NetworkMode.BROADCAST;
-    InetAddress destinationIp = null;
-    
-    try
-    {
-        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
-    }
-    catch(Exception e)
-    {
-        System.out.println(e + " Cannot create multicast address");
-        System.exit(0);
-    }
-    
-    // All system properties, passed in on the command line via -Dattribute=value
-    Properties systemProperties = System.getProperties();
-    
-    // IP address we send to
-    String destinationIpString = systemProperties.getProperty("destinationIp");
-    
-    // Port we send to, and local port we open the socket on
-    String portString = systemProperties.getProperty("port");
-    
-    // Network mode: unicast, multicast, broadcast
-    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
-        
-
-    // Set up a socket to send information
-    try
-    {
-        // Port we send to
-        if(portString != null)
-            port = Integer.parseInt(portString);
-        
-        socket = new MulticastSocket(port);
-        
-        // Where we send packets to, the destination IP address
-        if(destinationIpString != null)
-        {
-            destinationIp = InetAddress.getByName(destinationIpString);
-        }
-
-        // Type of transport: unicast, broadcast, or multicast
-        if(networkModeString != null)
-        {
-            if(networkModeString.equalsIgnoreCase("unicast"))
-                mode = NetworkMode.UNICAST;
-            else if(networkModeString.equalsIgnoreCase("broadcast"))
-                mode = NetworkMode.BROADCAST;
-            else if(networkModeString.equalsIgnoreCase("multicast"))
-            {
-                mode = NetworkMode.MULTICAST;
-                if(!destinationIp.isMulticastAddress())
-                {
-                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
-                }
-                
-                socket.joinGroup(destinationIp);
-                
-            }
-        } // end networkModeString
-    }
-    catch(Exception e)
-    {
-        System.out.println("Unable to initialize networking. Exiting.");
-        System.out.println(e);
-        System.exit(-1);
-    }
-    
-    // Initialize values in the Entity State PDU object. The exercise ID is 
-    // a way to differentiate between different virtual worlds on one network.
-    // Note that some values (such as the PDU type and PDU family) are set
-    // automatically when you create the ESPDU.
-    espdu.setExerciseID((short)1);
-    
-    // The EID is the unique identifier for objects in the world. This 
-    // EID should match up with the ID for the object specified in the 
-    // VMRL/x3d/virtual world.
-    EntityID eid = espdu.getEntityID();
-    eid.setSite(1);  // 0 is apparently not a valid site number, per the spec
-    eid.setApplication(1); 
-    eid.setEntity(2); 
-    
-    // Set the entity type. SISO has a big list of enumerations, so that by
-    // specifying various numbers we can say this is an M1A2 American tank,
-    // the USS Enterprise, and so on. We'll make this a tank. There is a 
-    // separate project elsehwhere in this project that implements DIS 
-    // enumerations in C++ and Java, but to keep things simple we just use
-    // numbers here.
-    EntityType entityType = espdu.getEntityType();
-    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
-    entityType.setCountry(225);              // USA
-    entityType.setDomain((short)1);          // Land (vs air, surface, subsurface, space)
-    entityType.setCategory((short)1);        // Tank
-    entityType.setSubcategory((short)1);     // M1 Abrams
-    entityType.setSpec((short)3);            // M1A2 Abrams
-    
-
-    Set<InetAddress> bcastAddresses = getBroadcastAddresses();
-    // Loop through sending N ESPDUs
-    try
-    {
-        System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
-        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
-        {
-            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
-            // hour, and time is set to DIS time units from the top of the hour. 
-            // This means that if you start sending just before the top of the hour
-            // the time units can roll over to zero as you are sending. The receivers
-            // (escpecially homegrown ones) are often not able to detect rollover
-            // and may start discarding packets as dupes or out of order. We use
-            // an NPS timestamp here, hundredths of a second since the start of the
-            // year. The DIS standard for time is often ignored in the wild; I've seen
-            // people use Unix time (seconds since 1970) and more. Or you can
-            // just stuff idx into the timestamp field to get something that is monotonically
-            // increasing.
-            
-            // Note that timestamp is used to detect duplicate and out of order packets. 
-            // That means if you DON'T change the timestamp, many implementations will simply
-            // discard subsequent packets that have an identical timestamp. Also, if they
-            // receive a PDU with an timestamp lower than the last one they received, they
-            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
-            // update the timestamp on ALL packets sent.
-            
-
-            // An alterative approach: actually follow the standard. It's a crazy concept,
-            // but it might just work.
-            int ts = disTime.getDisAbsoluteTimestamp();
-            espdu.setTimestamp(ts);
-            
-            // Set the position of the entity in the world. DIS uses a cartesian 
-            // coordinate system with the origin at the center of the earth, the x
-            // axis out at the equator and prime meridian, y out at the equator and
-            // 90 deg east, and z up and out the north pole. To place an object on
-            // the earth's surface you also need a model for the shape of the earth
-            // (it's not a sphere.) All the fancy math necessary to do this is in
-            // the SEDRIS SRM package. There are also some one-off formulas for 
-            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
-            // Here we use those one-off formulas.
-
-            // Modify the position of the object. This will send the object a little
-            // due east by adding some to the longitude every iteration. Since we
-            // are on the Pacific coast, this sends the object east. Assume we are
-            // at zero altitude. In other worlds you'd use DTED to determine the
-            // local ground altitude at that lat/lon, or you'd just use ground clamping.
-            // The x and y values will change, but the z value should not.
-            
-            //lon = lon + (double)((double)idx / 100000.0);
-            //System.out.println("lla=" + lat + "," + lon + ", 0.0");
-
-            double direction = Math.pow((double)(-1.0), (double)(idx));
-            lon = lon + (direction * 0.00006);
-            System.out.println(lon);
-            
-            double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
-            Vector3Double location = espdu.getEntityLocation();
-            location.setX(disCoordinates[0]);
-            location.setY(disCoordinates[1]);
-            location.setZ(disCoordinates[2]);
-            System.out.println("lat, lon:" + lat + ", " + lon);
-            System.out.println("DIS coord:" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
-
-            // Optionally, we can do some rotation of the entity
-            /*
-            Orientation orientation = espdu.getEntityOrientation();
-            float psi = orientation.getPsi();
-            psi = psi + idx;
-            orientation.setPsi(psi);
-            orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
-             */
-            
-            // You can set other ESPDU values here, such as the velocity, acceleration,
-            // and so on.
-
-            // Marshal out the espdu object to a byte array, then send a datagram
-            // packet with that data in it.
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            DataOutputStream dos = new DataOutputStream(baos);
-            espdu.marshal(dos);
-
-            FirePdu fire = new FirePdu();
-            byte[] fireArray = fire.marshal();
-            
-            // The byte array here is the packet in DIS format. We put that into a 
-            // datagram and send it.
-            byte[] data = baos.toByteArray();
-
-            bcastAddresses = getBroadcastAddresses();
-            Iterator it = bcastAddresses.iterator();
-            while(it.hasNext())
-            {
-               InetAddress bcast = (InetAddress)it.next();
-               System.out.println("Sending bcast to " + bcast);
-               DatagramPacket packet = new DatagramPacket(data, data.length, bcast, 3000);
-               socket.send(packet);
-               packet = new DatagramPacket(fireArray, fireArray.length, bcast, 3000);
-               //socket.send(packet);
-            }
-            
-            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
-            Thread.sleep(3000);
-
-            location = espdu.getEntityLocation();
-            
-            System.out.println("Espdu #" + idx + " EID=[" + eid.getSite() + "," + eid.getApplication() + "," + eid.getEntity() + "]");
-            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
-            double c[] = {location.getX(), location.getY(), location.getZ()};
-            double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
-//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
-
-        }
-    }
-    catch(Exception e)
-    {
-        System.out.println(e);
-    }
-        
-}
-
- /**
-    * A number of sites get all snippy about using 255.255.255.255 for a bcast
-    * address; it trips their security software and they kick you off their 
-    * network. (Comcast, NPS.) This determines the bcast address for all
-    * connected interfaces, based on the IP and subnet mask. If you have
-    * a dual-homed host it will return a bcast address for both. If you have
-    * some VMs running on your host this will pick up the addresses for those
-    * as well--eg running VMWare on your laptop with a local IP this will
-    * also pick up a 192.168 address assigned to the VM by the host OS.
-    * 
-    * @return set of all bcast addresses
-    */
-   public static Set<InetAddress> getBroadcastAddresses()
-   {
-       Set<InetAddress> bcastAddresses = new HashSet<InetAddress>();
-       Enumeration interfaces;
-       
-       try
-       {
-           interfaces = NetworkInterface.getNetworkInterfaces();
-           
-           while(interfaces.hasMoreElements())
-           {
-               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
-               
-               if(anInterface.isUp())
-               {
-                   Iterator it = anInterface.getInterfaceAddresses().iterator();
-                   while(it.hasNext())
-                   {
-                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
-                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
-                           continue;
-                       
-                       //System.out.println("Getting bcast address for " + anAddress);
-                       InetAddress abcast = anAddress.getBroadcast();
-                       if(abcast != null)
-                        bcastAddresses.add(abcast);
-                   }
-               }
-           }
-           
-       }
-       catch(Exception e)
-       {
-           e.printStackTrace();
-           System.out.println(e);
-       }
-       
-       return bcastAddresses;   
-   }
-
-}
+// package edu.nps.moves.examples; // copy example from OpenDIS distribution, modify to serve as template
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import edu.nps.moves.dis.*;
+import edu.nps.moves.disutil.CoordinateConversions;
+import edu.nps.moves.disutil.DisTime;
+
+/**
+ * Creates and sends ESPDUs in IEEE binary format. 
+ *
+ * @author DMcG
+ */
+public class ConardSnellOpenDisEspduSender 
+{
+    public static final int NUMBER_TO_SEND = 5000;
+
+    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
+
+    /** Default multicast group address we send on */
+    public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
+   
+    /** Default port we send on */
+    public static final int    DIS_DESTINATION_PORT = 3000;
+    
+/** Possible system properties, passed in via -Dattr=val
+     * networkMode: unicast, broadcast, multicast
+     * destinationIp: where to send the packet. If in multicast mode, this can be multicast.
+     *                To determine broadcast destination IP, use an online broadcast address
+     *                calculator, for example http://www.remotemonitoringsystems.ca/broadcast.php
+     *                If in multicast mode, a join() will be done on the multicast address.
+     * port: port used for both source and destination.
+     * @param args 
+     */
+public static void main(String args[])
+{
+    /** an entity state pdu */
+    EntityStatePdu espdu = new EntityStatePdu();
+    MulticastSocket socket = null; // must be initialized, even if null
+    DisTime disTime = DisTime.getInstance(); // TODO explain
+    int alternator = -1;
+    
+    // ICBM coordinates for my office
+    double lat = 36.595517; 
+    double lon = -121.877000;
+    
+    // Default settings. These are used if no system properties are set. 
+    // If system properties are passed in, these are over ridden.
+    int port = DIS_DESTINATION_PORT;
+    NetworkMode mode = NetworkMode.BROADCAST;
+    InetAddress destinationIp = null; // must be initialized, even if null
+    
+    try
+    {
+        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
+    }
+    catch(UnknownHostException e)
+    {
+        System.out.println(e + " Cannot create multicast address");
+        System.exit(0);
+    }
+    
+    // All system properties, passed in on the command line via -Dattribute=value
+    Properties systemProperties = System.getProperties();
+    
+    // IP address we send to
+    String destinationIpString = systemProperties.getProperty("destinationIp");
+    
+    // Port we send to, and local port we open the socket on
+    String portString = systemProperties.getProperty("port");
+    
+    // Network mode: unicast, multicast, broadcast
+    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
+        
+    // Set up a socket to send information
+    try
+    {
+        // Port we send to
+        if(portString != null)
+            port = Integer.parseInt(portString);
+        
+        socket = new MulticastSocket(port);
+        
+        // Where we send packets to, the destination IP address
+        if(destinationIpString != null)
+        {
+            destinationIp = InetAddress.getByName(destinationIpString);
+        }
+
+        // Type of transport: unicast, broadcast, or multicast
+		// TODO convert to String constants
+        if(networkModeString != null)
+        {
+            if(networkModeString.equalsIgnoreCase("unicast"))
+                mode = NetworkMode.UNICAST;
+            else if(networkModeString.equalsIgnoreCase("broadcast"))
+                mode = NetworkMode.BROADCAST;
+            else if(networkModeString.equalsIgnoreCase("multicast"))
+            {
+                mode = NetworkMode.MULTICAST;
+                if(!destinationIp.isMulticastAddress())
+                {
+                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
+                }
+                
+                socket.joinGroup(destinationIp);
+            }
+        } // end networkModeString
+    }
+    catch(IOException | RuntimeException e)
+    {
+        System.out.println("Unable to initialize networking. Exiting.");
+        System.out.println(e);
+        System.exit(-1);
+    }
+    
+    // Initialize values in the Entity State PDU object. The exercise ID is 
+    // a way to differentiate between different virtual worlds on one network.
+    // Note that some values (such as the PDU type and PDU family) are set
+    // automatically when you create the ESPDU.
+    espdu.setExerciseID((short)1);
+    
+    // The EID is the unique identifier for objects in the world. This 
+    // EID should match up with the ID for the object specified in the 
+    // VMRL/x3d/virtual world.
+    EntityID entityID = espdu.getEntityID();
+    entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
+    entityID.setApplication(1); 
+    entityID.setEntity(2); 
+    
+    // Set the entity type. SISO has a big list of enumerations, so that by
+    // specifying various numbers we can say this is an M1A2 American tank,
+    // the USS Enterprise, and so on. We'll make this a tank. There is a 
+    // separate project elsehwhere in this project that implements DIS 
+    // enumerations in C++ and Java, but to keep things simple we just use
+    // numbers here.
+    EntityType entityType = espdu.getEntityType();
+    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
+    entityType.setCountry(225);              // USA
+    entityType.setDomain((short)1);          // Land (vs air, surface, subsurface, space)
+    entityType.setCategory((short)1);        // Tank
+    entityType.setSubcategory((short)1);     // M1 Abrams
+    entityType.setSpec((short)3);            // M1A2 Abrams
+    
+
+    Set<InetAddress> broadcastAddresses;
+    // Loop through sending N ESPDUs
+    try
+    {
+        System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
+        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
+        {
+            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
+            // hour, and time is set to DIS time units from the top of the hour. 
+            // This means that if you start sending just before the top of the hour
+            // the time units can roll over to zero as you are sending. The receivers
+            // (escpecially homegrown ones) are often not able to detect rollover
+            // and may start discarding packets as dupes or out of order. We use
+            // an NPS timestamp here, hundredths of a second since the start of the
+            // year. The DIS standard for time is often ignored in the wild; I've seen
+            // people use Unix time (seconds since 1970) and more. Or you can
+            // just stuff idx into the timestamp field to get something that is monotonically
+            // increasing.
+            
+            // Note that timestamp is used to detect duplicate and out of order packets. 
+            // That means if you DON'T change the timestamp, many implementations will simply
+            // discard subsequent packets that have an identical timestamp. Also, if they
+            // receive a PDU with an timestamp lower than the last one they received, they
+            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
+            // update the timestamp on ALL packets sent.
+            
+
+            // An alterative approach: actually follow the standard. It's a crazy concept,
+            // but it might just work.
+            int timestamp = disTime.getDisAbsoluteTimestamp();
+            espdu.setTimestamp(timestamp);
+            
+            // Set the position of the entity in the world. DIS uses a cartesian 
+            // coordinate system with the origin at the center of the earth, the x
+            // axis out at the equator and prime meridian, y out at the equator and
+            // 90 deg east, and z up and out the north pole. To place an object on
+            // the earth's surface you also need a model for the shape of the earth
+            // (it's not a sphere.) All the fancy math necessary to do this is in
+            // the SEDRIS SRM package. There are also some one-off formulas for 
+            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
+            // Here we use those one-off formulas.
+
+            // Modify the position of the object. This will send the object a little
+            // due east by adding some to the longitude every iteration. Since we
+            // are on the Pacific coast, this sends the object east. Assume we are
+            // at zero altitude. In other worlds you'd use DTED to determine the
+            // local ground altitude at that lat/lon, or you'd just use ground clamping.
+            // The x and y values will change, but the z value should not.
+            
+            //lon = lon + (double)((double)idx / 100000.0);
+            //System.out.println("lla=" + lat + "," + lon + ", 0.0");
+
+//            double direction = Math.pow((double)(-1.0), (double)(idx));
+            lon = Math.cos(idx)*20;
+            lat = Math.sin(idx)*20;
+//            lon = lon + (direction * 0.00006);
+//            System.out.println(lon);
+            
+            double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
+            Vector3Double location = espdu.getEntityLocation();
+            location.setX(disCoordinates[0]);
+            location.setY(disCoordinates[1]);
+            location.setZ(disCoordinates[2]);
+            System.out.println("lat, lon:" + lat + ", " + lon);
+            System.out.println("DIS coord:" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
+
+            // Optionally, we can do some rotation of the entity
+            /*
+            Orientation orientation = espdu.getEntityOrientation();
+            float psi = orientation.getPsi();
+            psi = psi + idx;
+            orientation.setPsi(psi);
+            orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
+             */
+            
+            // You can set other ESPDU values here, such as the velocity, acceleration,
+            // and so on.
+
+            // Marshal out the espdu object to a byte array, then send a datagram
+            // packet with that data in it.
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            DataOutputStream dos = new DataOutputStream(baos);
+            espdu.marshal(dos);
+
+            FirePdu fire = new FirePdu();
+            byte[] fireArray = fire.marshal();
+            
+            // The byte array here is the packet in DIS format. We put that into a 
+            // datagram and send it.
+            byte[] data = baos.toByteArray();
+
+            broadcastAddresses = getBroadcastAddresses();
+            Iterator it = broadcastAddresses.iterator();
+            while(it.hasNext())
+            {
+               InetAddress broadcast = (InetAddress)it.next();
+               System.out.println("Sending broadcast datagram packet to " + broadcast);
+               DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, 3000);
+               socket.send(packet);
+			   // TODO experiment with these!  8)
+               packet = new DatagramPacket(fireArray, fireArray.length, broadcast, 3000); // alternate
+               socket.send(packet);
+            }
+            
+            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
+            Thread.sleep(3000);
+
+            location = espdu.getEntityLocation();
+            
+            System.out.println("Espdu #" + idx + " EID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
+            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
+            double c[] = {location.getX(), location.getY(), location.getZ()};
+            double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
+//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
+
+        }
+    }
+    catch(IOException | InterruptedException e)
+    {
+        System.out.println(e);
+    }
+        
+}
+
+ /**
+    * A number of sites get all snippy about using 255.255.255.255 for a broadcast
+    * address; it trips their security software and they kick you off their 
+    * network. (Comcast, NPS.) This determines the broadcast address for all
+    * connected interfaces, based on the IP and subnet mask. If you have
+    * a dual-homed host it will return a broadcast address for both. If you have
+    * some VMs running on your host this will pick up the addresses for those
+    * as well--eg running VMWare on your laptop with a local IP this will
+    * also pick up a 192.168 address assigned to the VM by the host OS.
+    * 
+    * @return set of all broadcast addresses
+    */
+   public static Set<InetAddress> getBroadcastAddresses()
+   {
+       Set<InetAddress> broadcastAddresses = new HashSet<>();
+       Enumeration interfaces;
+       
+       try
+       {
+           interfaces = NetworkInterface.getNetworkInterfaces();
+           
+           while(interfaces.hasMoreElements())
+           {
+               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
+               
+               if(anInterface.isUp())
+               {
+                   Iterator it = anInterface.getInterfaceAddresses().iterator();
+                   while(it.hasNext())
+                   {
+                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
+                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
+                           continue;
+                       
+                       //System.out.println("Getting broadcast address for " + anAddress);
+                       InetAddress broadcastAddress = anAddress.getBroadcast();
+                       if(broadcastAddress != null)
+                          broadcastAddresses.add(broadcastAddress);
+                   }
+               }
+           }
+           
+       }
+       catch(SocketException e)
+       {
+           e.printStackTrace();
+           System.out.println(e);
+       }
+       
+       return broadcastAddresses;   
+   }
+
+}
diff --git a/projects/Assignments/homework3/ConardSnellREADME.md b/projects/Assignments/homework3/ConardSnellREADME.md
new file mode 100644
index 0000000000000000000000000000000000000000..e8ed374f19f418ece8b55675e3738cf042ecf265
--- /dev/null
+++ b/projects/Assignments/homework3/ConardSnellREADME.md
@@ -0,0 +1,24 @@
+## Homework Assignment 3 Checklist
+
+1. [x] Add X3D-Edit as Netbeans Plugin from https://savage.nps.edu/X3D-Edit/#Downloads
+
+1. [x] Optional: checkout Open-DIS-Java library source from https://github.com/open-dis/open-dis-java
+
+1. [x] Otherwise just inspect files of interest from
+   [edu.nps.moves.examples](https://github.com/open-dis/open-dis-java/tree/master/src/main/java/edu/nps/moves/examples)
+
+1. [x] Copy README.md and create YournameREADME.md documentation file...
+
+1. [x] Plan a track of interest, described in YournameREADME.md documentation file...
+
+1. [x] Copy, then Refactor/Rename example file OpenDisEspduSender.java or OpenDisPduSender.java as YourNameSomething.java
+
+1. [x] Modify your example file to produce track PDUs (and be cool)
+
+1. [x] Generate PDUs...
+
+1. [x] Test PDU reading using Wireshark...
+
+1. [x] Record PDU file using X3D-Edit...
+
+1. [x] Playback PDU file using X3D-Edit...
diff --git a/projects/Assignments/homework3/ConardSnelldispackets.disbin b/projects/Assignments/homework3/ConardSnelldispackets.disbin
new file mode 100644
index 0000000000000000000000000000000000000000..4659ec9fc4630f41171421cb6370a8e141530720
Binary files /dev/null and b/projects/Assignments/homework3/ConardSnelldispackets.disbin differ
diff --git a/projects/Assignments/AngelBlankFP/EspduReceiver.java b/projects/Assignments/homework3/EspduReceiver.java
similarity index 100%
rename from projects/Assignments/AngelBlankFP/EspduReceiver.java
rename to projects/Assignments/homework3/EspduReceiver.java
diff --git a/projects/Assignments/AngelBlankFP/EspduSender.java b/projects/Assignments/homework3/EspduSender_1.java
similarity index 100%
rename from projects/Assignments/AngelBlankFP/EspduSender.java
rename to projects/Assignments/homework3/EspduSender_1.java
diff --git a/projects/Assignments/homework3/HanleyREADME.md b/projects/Assignments/homework3/HanleyREADME.md
index 0344525a6c5aa91776b09d34ba16bbfc9c4c7057..9d3784a7dc2868d5a97581bfd594512ab3f1f79e 100644
--- a/projects/Assignments/homework3/HanleyREADME.md
+++ b/projects/Assignments/homework3/HanleyREADME.md
@@ -17,7 +17,7 @@
 
 1. [X] Generate PDUs...
 
-1. [ ] Test PDU reading using Wireshark... Still working (06MAR)
+1. [x] Test PDU reading using Wireshark...
 
 1. [x] Record PDU file using X3D-Edit...
 
@@ -31,3 +31,488 @@ Track of Interest
 Modify your example file to produce track PDUs (and be cool)
     modified direction of travel by adding latitude displacement.  Tried to add 
     an angular velocity, but could not get it to work
+
+
+Wireshark output:
+920	178.601803	172.20.152.80	172.20.159.255	DIS	186	PDUType: 1 	 Entity State, Platform, Land, (1:1:2)
+942	181.792430	172.20.152.80	172.20.159.255	DIS	186	PDUType: 1 	 Entity State, Platform, Land, (1:1:2)
+
+
+Output from runningHanley_OpnDisEspduSender
+ant -f C:\\Users\\Brian\\Documents\\NetBeansProjects\\NetworkedGraphicsMV3500(try2)\\NetworkedGraphicsMV3500\\projects\\Assignments -Djavac.includes=Hanley_OpenDisEspduSender.java -Dnb.internal.action.name=run.single -Drun.class=Hanley_OpenDisEspduSender run-single
+init:
+Deleting: C:\Users\Brian\Documents\NetBeansProjects\NetworkedGraphicsMV3500(try2)\NetworkedGraphicsMV3500\projects\Assignments\build\built-jar.properties
+deps-jar:
+Updating property file: C:\Users\Brian\Documents\NetBeansProjects\NetworkedGraphicsMV3500(try2)\NetworkedGraphicsMV3500\projects\Assignments\build\built-jar.properties
+Compiling 1 source file to C:\Users\Brian\Documents\NetBeansProjects\NetworkedGraphicsMV3500(try2)\NetworkedGraphicsMV3500\projects\Assignments\build\classes
+compile-single:
+run-single:
+Sending 5000 ESPDU packets to /239.1.2.3
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #0 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #1 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #2 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #3 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #4 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #5 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #6 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #7 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #8 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #9 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #10 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #11 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #12 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #13 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #14 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #15 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #16 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #17 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #18 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #19 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #20 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #21 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #22 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #23 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #24 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #25 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #26 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #27 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #28 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #29 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #30 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #31 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #32 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #33 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #34 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #35 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #36 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #37 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #38 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #39 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #40 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #41 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #42 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #43 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #44 EID=[1,1,2]
+ DIS coordinates location=[-2707484.0531117637,-4353663.186028796,3781457.4477844355]
+ Location (lat/lon/alt): [36.595597, -121.87692000000001, 0.9999999990686774]
+-121.877
+lat, lon:36.595517, -121.877
+DIS coord:-2707492.9269245286, -4353663.899966802, 3781450.3202754413
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+Espdu #45 EID=[1,1,2]
+ DIS coordinates location=[-2707492.9269245286,-4353663.899966802,3781450.3202754413]
+ Location (lat/lon/alt): [36.59551700000001, -121.877, 0.9999999990686774]
+-121.87692
+lat, lon:36.595597, -121.87692
+DIS coord:-2707484.0531117637, -4353663.186028796, 3781457.4477844355
+Sending broadcast datagram packet to /127.255.255.255
+Sending broadcast datagram packet to /192.168.112.255
+Sending broadcast datagram packet to /192.168.111.255
+Sending broadcast datagram packet to /172.20.159.255
+BUILD STOPPED (total time: 2 minutes 29 seconds)
diff --git a/projects/Assignments/homework3/Hanley_OpenDisEspduSender.java b/projects/Assignments/homework3/Hanley_OpenDisEspduSender.java
index 6a469fbc0c45d30b7ed6f9019060360072e4f9f4..99739f39c44d864bc30e9bc2c36b0b37a05eb03c 100644
--- a/projects/Assignments/homework3/Hanley_OpenDisEspduSender.java
+++ b/projects/Assignments/homework3/Hanley_OpenDisEspduSender.java
@@ -257,7 +257,7 @@ public static void main(String args[])
             System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
             double c[] = {location.getX(), location.getY(), location.getZ()};
             double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
-//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
+            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
 
         }
     }
diff --git a/projects/Assignments/homework3/LandasREADME.md b/projects/Assignments/homework3/LandasREADME.md
new file mode 100644
index 0000000000000000000000000000000000000000..4f4db0c3aec7ea13bd39745381107b1fd36d8e86
--- /dev/null
+++ b/projects/Assignments/homework3/LandasREADME.md
@@ -0,0 +1,41 @@
+## Homework Assignment 3 Checklist
+
+1. [x] Add X3D-Edit as Netbeans Plugin from https://savage.nps.edu/X3D-Edit/#Downloads
+
+1. [x] Optional: checkout Open-DIS-Java library source from https://github.com/open-dis/open-dis-java
+
+1. [x] Otherwise just inspect files of interest from
+   [edu.nps.moves.examples](https://github.com/open-dis/open-dis-java/tree/master/src/main/java/edu/nps/moves/examples)
+
+1. [x] Copy README.md and create YournameREADME.md documentation file...
+
+1. [x] Plan a track of interest, described in YournameREADME.md documentation file...
+
+1. [x] Copy, then Refactor/Rename example file OpenDisEspduSender.java or OpenDisPduSender.java as YourNameSomething.java
+
+1. [x] Modify your example file to produce track PDUs (and be cool)
+
+1. [x] Generate PDUs...
+
+1. [x] Test PDU reading using Wireshark...
+
+1. [x] Record PDU file using X3D-Edit...
+
+1. [x] Playback PDU file using X3D-Edit...
+
+
+
+Track of interest (my route to school):
+36.585657, -121.879920
+36.584853, -121.880024
+36.583500, -121.879615
+36.586307, -121.874582
+36.588670, -121.877928
+36.591124, -121.880074
+36.592827, -121.877149
+36.594051, -121.877452
+36.594245, -121.876477
+36.595230, -121.877537
+
+
+
diff --git a/projects/Assignments/homework3/Landas_Assignment3_dispackets.disbin b/projects/Assignments/homework3/Landas_Assignment3_dispackets.disbin
new file mode 100644
index 0000000000000000000000000000000000000000..d542f4b554d4d03eabeeb2e13be49b45c1ead69b
Binary files /dev/null and b/projects/Assignments/homework3/Landas_Assignment3_dispackets.disbin differ
diff --git a/projects/Assignments/homework3/Landas_Assignment3_dispackets.disbin.disbinidx b/projects/Assignments/homework3/Landas_Assignment3_dispackets.disbin.disbinidx
new file mode 100644
index 0000000000000000000000000000000000000000..d033f7d48d0eaf5a23c8dda64764b172e742ba24
Binary files /dev/null and b/projects/Assignments/homework3/Landas_Assignment3_dispackets.disbin.disbinidx differ
diff --git a/projects/Assignments/homework3/Landas_OpenDisEspduSender.java b/projects/Assignments/homework3/Landas_OpenDisEspduSender.java
new file mode 100644
index 0000000000000000000000000000000000000000..34ba932bed05407b35103f1a65a38901861a0ca9
--- /dev/null
+++ b/projects/Assignments/homework3/Landas_OpenDisEspduSender.java
@@ -0,0 +1,385 @@
+// package edu.nps.moves.examples; // copy example from OpenDIS distribution, modify to serve as template
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import edu.nps.moves.dis.*;
+import edu.nps.moves.disutil.CoordinateConversions;
+import edu.nps.moves.disutil.DisTime;
+
+/**
+ * Creates and sends ESPDUs in IEEE binary format. 
+ *
+ * @author DMcG
+ */
+public class Landas_OpenDisEspduSender 
+{
+    public static final int NUMBER_TO_SEND = 5000;
+
+    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
+
+    /** Default multicast group address we send on */
+    public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
+   
+    /** Default port we send on */
+    public static final int    DIS_DESTINATION_PORT = 3000;
+    
+    private static final ArrayList <Float[]> track_coordinates = new ArrayList<>();
+    
+/** Possible system properties, passed in via -Dattr=val
+     * networkMode: unicast, broadcast, multicast
+     * destinationIp: where to send the packet. If in multicast mode, this can be multicast.
+     *                To determine broadcast destination IP, use an online broadcast address
+     *                calculator, for example http://www.remotemonitoringsystems.ca/broadcast.php
+     *                If in multicast mode, a join() will be done on the multicast address.
+     * port: port used for both source and destination.
+     * @param args 
+     */
+public static void main(String args[])
+{
+    /** an entity state pdu */
+    EntityStatePdu espdu = new EntityStatePdu();
+    MulticastSocket socket = null; // must be initialized, even if null
+    DisTime disTime = DisTime.getInstance(); // TODO explain
+    int alternator = -1;
+    
+    // ICBM coordinates for my office
+//    double lat = 36.595517; 
+//    double lon = -121.877000;
+    
+    // Default settings. These are used if no system properties are set. 
+    // If system properties are passed in, these are over ridden.
+    int port = DIS_DESTINATION_PORT;
+    NetworkMode mode = NetworkMode.BROADCAST;
+    InetAddress destinationIp = null; // must be initialized, even if null
+    
+    try
+    {
+        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
+    }
+    catch(UnknownHostException e)
+    {
+        System.out.println(e + " Cannot create multicast address");
+        System.exit(0);
+    }
+    
+    // All system properties, passed in on the command line via -Dattribute=value
+    Properties systemProperties = System.getProperties();
+    
+    // IP address we send to
+    String destinationIpString = systemProperties.getProperty("destinationIp");
+    
+    // Port we send to, and local port we open the socket on
+    String portString = systemProperties.getProperty("port");
+    
+    // Network mode: unicast, multicast, broadcast
+    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
+        
+    // Set up a socket to send information
+    try
+    {
+        // Port we send to
+        if(portString != null)
+            port = Integer.parseInt(portString);
+        
+        socket = new MulticastSocket(port);
+        
+        // Where we send packets to, the destination IP address
+        if(destinationIpString != null)
+        {
+            destinationIp = InetAddress.getByName(destinationIpString);
+        }
+
+        // Type of transport: unicast, broadcast, or multicast
+		// TODO convert to String constants
+        if(networkModeString != null)
+        {
+            if(networkModeString.equalsIgnoreCase("unicast"))
+                mode = NetworkMode.UNICAST;
+            else if(networkModeString.equalsIgnoreCase("broadcast"))
+                mode = NetworkMode.BROADCAST;
+            else if(networkModeString.equalsIgnoreCase("multicast"))
+            {
+                mode = NetworkMode.MULTICAST;
+                if(!destinationIp.isMulticastAddress())
+                {
+                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
+                }
+                
+                socket.joinGroup(destinationIp);
+            }
+        } // end networkModeString
+    }
+    catch(IOException | RuntimeException e)
+    {
+        System.out.println("Unable to initialize networking. Exiting.");
+        System.out.println(e);
+        System.exit(-1);
+    }
+    
+    // Initialize values in the Entity State PDU object. The exercise ID is 
+    // a way to differentiate between different virtual worlds on one network.
+    // Note that some values (such as the PDU type and PDU family) are set
+    // automatically when you create the ESPDU.
+    espdu.setExerciseID((short)1);
+    
+    // The EID is the unique identifier for objects in the world. This 
+    // EID should match up with the ID for the object specified in the 
+    // VMRL/x3d/virtual world.
+    EntityID entityID = espdu.getEntityID();
+    entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
+    entityID.setApplication(1); 
+    entityID.setEntity(2); 
+    
+    // Set the entity type. SISO has a big list of enumerations, so that by
+    // specifying various numbers we can say this is an M1A2 American tank,
+    // the USS Enterprise, and so on. We'll make this a tank. There is a 
+    // separate project elsehwhere in this project that implements DIS 
+    // enumerations in C++ and Java, but to keep things simple we just use
+    // numbers here.
+    EntityType entityType = espdu.getEntityType();
+    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
+    entityType.setCountry(225);              // USA
+    entityType.setDomain((short)1);          // Land (vs air, surface, subsurface, space)
+    entityType.setCategory((short)1);        // Tank
+    entityType.setSubcategory((short)20);     // Maintenance equipment trailer(20)
+    entityType.setSpec((short)3);            // M1A2 Abrams
+    
+
+    Set<InetAddress> broadcastAddresses;
+    // Loop through sending N ESPDUs
+    try
+    {
+        
+//         Point point = new Point();
+//            point.setX(1.5f);
+//            point.setY(1.9f);
+//        
+//         List<Point> track_coordinates = new ArrayList<Point>();
+//         track_coordinates.add(point);
+//         System.out.println("********" + track_coordinates);
+        
+//        ArrayList <Float[]> track_coordinates = new ArrayList<>();
+        
+        Float[] TrackCoor1 = new Float [2];
+        TrackCoor1[0] = 36.585657f;
+        TrackCoor1[1] = -121.879920f;
+        track_coordinates.add(TrackCoor1);
+        Float[] TrackCoor2 = new Float [2];
+        TrackCoor2[0] = 36.584853f;
+        TrackCoor2[1] = -121.880024f;
+        track_coordinates.add(TrackCoor2);
+        Float[] TrackCoor3 = new Float [2];
+        TrackCoor3[0] = 36.583500f;
+        TrackCoor3[1] = -121.879615f;
+        track_coordinates.add(TrackCoor3);
+        Float[] TrackCoor4 = new Float [2];
+        TrackCoor4[0] = 36.586307f;
+        TrackCoor4[1] = -121.874582f;
+        track_coordinates.add(TrackCoor4);
+        Float[] TrackCoor5 = new Float [2];
+        TrackCoor5[0] = 36.588670f;
+        TrackCoor5[1] = -121.877928f;
+        track_coordinates.add(TrackCoor5);
+        Float[] TrackCoor6 = new Float [2];
+        TrackCoor6[0] = 36.591124f;
+        TrackCoor6[1] = -121.880074f;
+        track_coordinates.add(TrackCoor6);
+        Float[] TrackCoor7 = new Float [2];
+        TrackCoor7[0] = 36.592827f;
+        TrackCoor7[1] = -121.877149f;
+        track_coordinates.add(TrackCoor7);
+        Float[] TrackCoor8 = new Float [2];
+        TrackCoor8[0] = 36.594051f;
+        TrackCoor8[1] = -121.877452f;
+        track_coordinates.add(TrackCoor8);
+        Float[] TrackCoor9 = new Float [2];
+        TrackCoor9[0] = 36.594245f;
+        TrackCoor9[1] = -121.876477f;
+        track_coordinates.add(TrackCoor9);
+        Float[] TrackCoor10 = new Float [2];
+        TrackCoor10[0] = 36.595230f;
+        TrackCoor10[1] = -121.877537f;
+        track_coordinates.add(TrackCoor10);
+//        System.out.println("********" + String.valueOf(track_coordinates[0]) );
+//        System.out.println("********" + track_coordinates.get(5)[1]);
+        
+        
+            
+//        System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
+//        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
+        for(int idx = 0; idx < 10; idx++)
+        {
+        System.out.println("Sending ESPDU packet " + idx + " to " + destinationIp.toString());
+            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
+            // hour, and time is set to DIS time units from the top of the hour. 
+            // This means that if you start sending just before the top of the hour
+            // the time units can roll over to zero as you are sending. The receivers
+            // (escpecially homegrown ones) are often not able to detect rollover
+            // and may start discarding packets as dupes or out of order. We use
+            // an NPS timestamp here, hundredths of a second since the start of the
+            // year. The DIS standard for time is often ignored in the wild; I've seen
+            // people use Unix time (seconds since 1970) and more. Or you can
+            // just stuff idx into the timestamp field to get something that is monotonically
+            // increasing.
+            
+            // Note that timestamp is used to detect duplicate and out of order packets. 
+            // That means if you DON'T change the timestamp, many implementations will simply
+            // discard subsequent packets that have an identical timestamp. Also, if they
+            // receive a PDU with an timestamp lower than the last one they received, they
+            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
+            // update the timestamp on ALL packets sent.
+            
+
+            // An alterative approach: actually follow the standard. It's a crazy concept,
+            // but it might just work.
+            int timestamp = disTime.getDisAbsoluteTimestamp();
+            espdu.setTimestamp(timestamp);
+            
+
+            // Set the position of the entity in the world. DIS uses a cartesian
+            // coordinate system with the origin at the center of the earth, the x
+            // axis out at the equator and prime meridian, y out at the equator and
+            // 90 deg east, and z up and out the north pole. To place an object on
+            // the earth's surface you also need a model for the shape of the earth
+            // (it's not a sphere.) All the fancy math necessary to do this is in
+            // the SEDRIS SRM package. There are also some one-off formulas for 
+            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
+            // Here we use those one-off formulas.
+            // Modify the position of the object. This will send the object a little
+            // due east by adding some to the longitude every iteration. Since we
+            // are on the Pacific coast, this sends the object east. Assume we are
+            // at zero altitude. In other worlds you'd use DTED to determine the
+            // local ground altitude at that lat/lon, or you'd just use ground clamping.
+            // The x and y values will change, but the z value should not.
+            //lon = lon + (double)((double)idx / 100000.0);
+            //System.out.println("lla=" + lat + "," + lon + ", 0.0");
+            Float lat = track_coordinates.get(idx)[0];
+            Float lon = track_coordinates.get(idx)[1];
+            
+//            double direction = Math.pow((double)(-1.0), (double)(idx));
+//            lon = lon + (direction * 0.00006);
+            
+            
+//            System.out.println(lon);
+            
+            double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
+            Vector3Double location = espdu.getEntityLocation();
+            location.setX(disCoordinates[0]);
+            location.setY(disCoordinates[1]);
+            location.setZ(disCoordinates[2]);
+            System.out.println("lat, lon: " + lat + ", " + lon);
+            System.out.println("DIS coord: " + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
+
+            // Optionally, we can do some rotation of the entity
+            /*
+            Orientation orientation = espdu.getEntityOrientation();
+            float psi = orientation.getPsi();
+            psi = psi + idx;
+            orientation.setPsi(psi);
+            orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
+             */
+            
+            // You can set other ESPDU values here, such as the velocity, acceleration,
+            // and so on.
+
+            // Marshal out the espdu object to a byte array, then send a datagram
+            // packet with that data in it.
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            DataOutputStream dos = new DataOutputStream(baos);
+            espdu.marshal(dos);
+
+            FirePdu fire = new FirePdu();
+            byte[] fireArray = fire.marshal();
+            
+            // The byte array here is the packet in DIS format. We put that into a 
+            // datagram and send it.
+            byte[] data = baos.toByteArray();
+
+            broadcastAddresses = getBroadcastAddresses();
+            Iterator it = broadcastAddresses.iterator();
+            while(it.hasNext())
+            {
+               InetAddress broadcast = (InetAddress)it.next();
+               System.out.println("Sending broadcast datagram packet to " + broadcast);
+               DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, 3000);
+               socket.send(packet);
+			   // TODO experiment with these!  8)
+//               packet = new DatagramPacket(fireArray, fireArray.length, broadcast, 3000); // alternate
+//               socket.send(packet);
+            }
+            
+            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
+            Thread.sleep(3000);
+
+            location = espdu.getEntityLocation();
+            
+            System.out.println("Espdu #" + idx + " EID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
+            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
+            double c[] = {location.getX(), location.getY(), location.getZ()};
+            double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
+//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
+
+        }
+    }
+    catch(IOException | InterruptedException e)
+    {
+        System.out.println(e);
+    }
+        
+}
+
+ /**
+    * A number of sites get all snippy about using 255.255.255.255 for a broadcast
+    * address; it trips their security software and they kick you off their 
+    * network. (Comcast, NPS.) This determines the broadcast address for all
+    * connected interfaces, based on the IP and subnet mask. If you have
+    * a dual-homed host it will return a broadcast address for both. If you have
+    * some VMs running on your host this will pick up the addresses for those
+    * as well--eg running VMWare on your laptop with a local IP this will
+    * also pick up a 192.168 address assigned to the VM by the host OS.
+    * 
+    * @return set of all broadcast addresses
+    */
+   public static Set<InetAddress> getBroadcastAddresses()
+   {
+       Set<InetAddress> broadcastAddresses = new HashSet<>();
+       Enumeration interfaces;
+       
+       try
+       {
+           interfaces = NetworkInterface.getNetworkInterfaces();
+           
+           while(interfaces.hasMoreElements())
+           {
+               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
+               
+               if(anInterface.isUp())
+               {
+                   Iterator it = anInterface.getInterfaceAddresses().iterator();
+                   while(it.hasNext())
+                   {
+                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
+                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
+                           continue;
+                       
+                       //System.out.println("Getting broadcast address for " + anAddress);
+                       InetAddress broadcastAddress = anAddress.getBroadcast();
+                       if(broadcastAddress != null)
+                          broadcastAddresses.add(broadcastAddress);
+                   }
+               }
+           }
+           
+       }
+       catch(SocketException e)
+       {
+           e.printStackTrace();
+           System.out.println(e);
+       }
+       
+       return broadcastAddresses;   
+   }
+
+}
diff --git a/projects/Assignments/homework3/Landas_OpenDisEspduSender.pdf b/projects/Assignments/homework3/Landas_OpenDisEspduSender.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..f4d55e584bcfee4ced1059c9e79e597e1a13179a
Binary files /dev/null and b/projects/Assignments/homework3/Landas_OpenDisEspduSender.pdf differ
diff --git a/projects/Assignments/homework3/OpenDisEspduSender.java b/projects/Assignments/homework3/OpenDisEspduSender.java
index f743ec74092fddc275c3730bdee124d66ca2ef96..fb6e9964a28054b36e55f230bbf2bf3b122a2fb7 100644
--- a/projects/Assignments/homework3/OpenDisEspduSender.java
+++ b/projects/Assignments/homework3/OpenDisEspduSender.java
@@ -21,6 +21,8 @@ public class OpenDisEspduSender
 
     /** Default multicast group address we send on */
     public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
+    
+    private static final ArrayList <Float[]> track = new ArrayList<>();
    
     /** Default port we send on */
     public static final int    DIS_DESTINATION_PORT = 3000;
@@ -43,8 +45,8 @@ public static void main(String args[])
     int alternator = -1;
     
     // ICBM coordinates for my office
-    double lat = 36.595517; 
-    double lon = -121.877000;
+    //double lat = 36.595517; 
+    //double lon = -121.877000;
     
     // Default settings. These are used if no system properties are set. 
     // If system properties are passed in, these are over ridden.
@@ -149,6 +151,46 @@ public static void main(String args[])
     // Loop through sending N ESPDUs
     try
     {
+        
+        Float[] TrackCoor1 = new Float [2];
+        TrackCoor1[0] = 36.59135f;
+        TrackCoor1[1] = -121.88051f;
+        track.add(TrackCoor1);
+        Float[] TrackCoor2 = new Float [2];
+        TrackCoor2[0] = 36.59487f;
+        TrackCoor2[1] = -121.86739f;
+        track.add(TrackCoor2);
+        Float[] TrackCoor3 = new Float [2];
+        TrackCoor3[0] = 36.63259f;
+        TrackCoor3[1] = -121.66926f;
+        track.add(TrackCoor3);
+        Float[] TrackCoor4 = new Float [2];
+        TrackCoor4[0] = 36.64481f;
+        TrackCoor4[1] = -121.61162f;
+        track.add(TrackCoor4);
+        Float[] TrackCoor5 = new Float [2];
+        TrackCoor5[0] = 35.64239f;
+        TrackCoor5[1] = -120.68503f;
+        track.add(TrackCoor5);
+        Float[] TrackCoor6 = new Float [2];
+        TrackCoor6[0] = 35.61577f;
+        TrackCoor6[1] = -119.65283f;
+        track.add(TrackCoor6);
+        Float[] TrackCoor7 = new Float [2];
+        TrackCoor7[0] = 34.76589f;
+        TrackCoor7[1] = -118.79854f;
+        track.add(TrackCoor7);
+        Float[] TrackCoor8 = new Float [2];
+        TrackCoor8[0] = 34.77651f;
+        TrackCoor8[1] = -118.17049f;
+        track.add(TrackCoor8);
+        Float[] TrackCoor9 = new Float [2];
+        TrackCoor9[0] = 34.5806f;
+        TrackCoor9[1] = -118.1334f;
+        track.add(TrackCoor9);
+        
+//        System.out.println("********" + String.valueOf(track_coordinates[0]) );
+//        System.out.println("********" + track_coordinates.get(5)[1]);
         System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
         for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
         {
@@ -197,9 +239,8 @@ public static void main(String args[])
             //lon = lon + (double)((double)idx / 100000.0);
             //System.out.println("lla=" + lat + "," + lon + ", 0.0");
 
-            double direction = Math.pow((double)(-1.0), (double)(idx));
-            lon = lon + (direction * 0.00006);
-            System.out.println(lon);
+            Float lat = track.get(idx)[0];
+            Float lon = track.get(idx)[1];
             
             double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
             Vector3Double location = espdu.getEntityLocation();
diff --git a/projects/Assignments/homework3/Sasala_HW3_Screenshots.pdf b/projects/Assignments/homework3/Sasala_HW3_Screenshots.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..49d03e35f7783db967736bbb1ed2072a60c1aba6
Binary files /dev/null and b/projects/Assignments/homework3/Sasala_HW3_Screenshots.pdf differ
diff --git a/projects/Assignments/homework3/ABEspduSenderA.java b/projects/Assignments/homework3/Sasala_OpenDisEspduSender1.java
similarity index 72%
rename from projects/Assignments/homework3/ABEspduSenderA.java
rename to projects/Assignments/homework3/Sasala_OpenDisEspduSender1.java
index d3cd7510899593dda0626ba0803f2903ba027146..fbe926fb1529c0b09dc730487e983d7d8e736a59 100644
--- a/projects/Assignments/homework3/ABEspduSenderA.java
+++ b/projects/Assignments/homework3/Sasala_OpenDisEspduSender1.java
@@ -1,323 +1,297 @@
-
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import edu.nps.moves.dis.*;
-import edu.nps.moves.disutil.CoordinateConversions;
-import edu.nps.moves.disutil.DisTime;
-
-/**
- * Creates and sends ESPDUs in IEEE binary format. 
- *
- * @author DMcG
- */
-public class ABEspduSenderA 
-{
-    public static final int NUMBER_TO_SEND = 5000;
-
-    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
-
-    /** default multicast group we send on */
-    public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
-   
-    /** Port we send on */
-    public static final int    DIS_DESTINATION_PORT = 3000;
-    
-/** Possible system properties, passed in via -Dattr=val
-     * networkMode: unicast, broadcast, multicast
-     * destinationIp: where to send the packet. If in multicast mode, this can be mcast.
-     *                To determine bcast destination IP, use an online bcast address
-     *                caclulator, for example http://www.remotemonitoringsystems.ca/broadcast.php
-     *                If in mcast mode, a join() will be done on the mcast address.
-     * port: port used for both source and destination.
-     * @param args 
-     */
-public static void main(String args[])
-{
-    /** an entity state pdu */
-    EntityStatePdu espdu = new EntityStatePdu();
-    MulticastSocket socket = null;
-    DisTime disTime = DisTime.getInstance();
-    int alternator = -1;
-    
-    // ICBM coordinates for my office
-    double lat = 36.595517; 
-    double lon = -121.877000;
-
-    
-    // Default settings. These are used if no system properties are set. 
-    // If system properties are passed in, these are over ridden.
-    int port = DIS_DESTINATION_PORT;
-    NetworkMode mode = NetworkMode.MULTICAST;
-    InetAddress destinationIp = null;
-    
-    try
-    {
-        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
-    }
-    catch(Exception e)
-    {
-        System.out.println(e + " Cannot create multicast address");
-        System.exit(0);
-    }
-    
-    // All system properties, passed in on the command line via -Dattribute=value
-    Properties systemProperties = System.getProperties();
-    
-    // IP address we send to
-    String destinationIpString = systemProperties.getProperty("destinationIp");
-    
-    // Port we send to, and local port we open the socket on
-    String portString = systemProperties.getProperty("port");
-    
-    // Network mode: unicast, multicast, broadcast
-    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
-        
-
-    // Set up a socket to send information
-    try
-    {
-        // Port we send to
-        if(portString != null)
-            port = Integer.parseInt(portString);
-        
-        socket = new MulticastSocket(port);
-        
-        // Where we send packets to, the destination IP address
-        if(destinationIpString != null)
-        {
-            destinationIp = InetAddress.getByName(destinationIpString);
-        }
-
-        // Type of transport: unicast, broadcast, or multicast
-        if(networkModeString != null)
-        {
-            if(networkModeString.equalsIgnoreCase("unicast"))
-                mode = NetworkMode.UNICAST;
-            else if(networkModeString.equalsIgnoreCase("broadcast"))
-                mode = NetworkMode.BROADCAST;
-            else if(networkModeString.equalsIgnoreCase("multicast"))
-            {
-                mode = NetworkMode.MULTICAST;
-                if(!destinationIp.isMulticastAddress())
-                {
-                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
-                }
-                
-                socket.joinGroup(destinationIp);
-                
-            }
-        } // end networkModeString
-    }
-    catch(Exception e)
-    {
-        System.out.println("Unable to initialize networking. Exiting.");
-        System.out.println(e);
-        System.exit(-1);
-    }
-    
-    // Initialize values in the Entity State PDU object. The exercise ID is 
-    // a way to differentiate between different virtual worlds on one network.
-    // Note that some values (such as the PDU type and PDU family) are set
-    // automatically when you create the ESPDU.
-    espdu.setExerciseID((short)1);
-    
-    // The EID is the unique identifier for objects in the world. This 
-    // EID should match up with the ID for the object specified in the 
-    // VMRL/x3d/virtual world.
-    EntityID eid = espdu.getEntityID();
-    eid.setSite(1);  // 0 is apparently not a valid site number, per the spec
-    eid.setApplication(1); 
-    eid.setEntity(2); 
-    
-    // Set the entity type. SISO has a big list of enumerations, so that by
-    // specifying various numbers we can say this is an M1A2 American tank,
-    // the USS Enterprise, and so on. We'll make this a tank. There is a 
-    // separate project elsehwhere in this project that implements DIS 
-    // enumerations in C++ and Java, but to keep things simple we just use
-    // numbers here.
-    EntityType entityType = espdu.getEntityType();
-    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
-    entityType.setCountry(225);              // USA
-    entityType.setDomain((short)1);          // Land (vs air, surface, subsurface, space)
-    entityType.setCategory((short)1);        // Tank
-    entityType.setSubcategory((short)1);     // M1 Abrams
-    entityType.setSpec((short)3);            // M1A2 Abrams
-    
-
-    Set<InetAddress> bcastAddresses = getBroadcastAddresses();
-    // Loop through sending N ESPDUs
-    try
-    {
-        System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
-        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
-        {
-            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
-            // hour, and time is set to DIS time units from the top of the hour. 
-            // This means that if you start sending just before the top of the hour
-            // the time units can roll over to zero as you are sending. The receivers
-            // (escpecially homegrown ones) are often not able to detect rollover
-            // and may start discarding packets as dupes or out of order. We use
-            // an NPS timestamp here, hundredths of a second since the start of the
-            // year. The DIS standard for time is often ignored in the wild; I've seen
-            // people use Unix time (seconds since 1970) and more. Or you can
-            // just stuff idx into the timestamp field to get something that is monotonically
-            // increasing.
-            
-            // Note that timestamp is used to detect duplicate and out of order packets. 
-            // That means if you DON'T change the timestamp, many implementations will simply
-            // discard subsequent packets that have an identical timestamp. Also, if they
-            // receive a PDU with an timestamp lower than the last one they received, they
-            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
-            // update the timestamp on ALL packets sent.
-            
-
-            // An alterative approach: actually follow the standard. It's a crazy concept,
-            // but it might just work.
-            int ts = disTime.getDisAbsoluteTimestamp();
-            espdu.setTimestamp(ts);
-            
-            // Set the position of the entity in the world. DIS uses a cartesian 
-            // coordinate system with the origin at the center of the earth, the x
-            // axis out at the equator and prime meridian, y out at the equator and
-            // 90 deg east, and z up and out the north pole. To place an object on
-            // the earth's surface you also need a model for the shape of the earth
-            // (it's not a sphere.) All the fancy math necessary to do this is in
-            // the SEDRIS SRM package. There are also some one-off formulas for 
-            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
-            // Here we use those one-off formulas.
-
-            // Modify the position of the object. This will send the object a little
-            // due east by adding some to the longitude every iteration. Since we
-            // are on the Pacific coast, this sends the object east. Assume we are
-            // at zero altitude. In other worlds you'd use DTED to determine the
-            // local ground altitude at that lat/lon, or you'd just use ground clamping.
-            // The x and y values will change, but the z value should not.
-            
-            //lon = lon + (double)((double)idx / 100000.0);
-            //System.out.println("lla=" + lat + "," + lon + ", 0.0");
-
-            double direction = Math.pow((double)(-1.0), (double)(idx));
-            lon = lon + (direction * 0.00006);
-            System.out.println(lon);
-            
-            double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
-            Vector3Double location = espdu.getEntityLocation();
-            location.setX(disCoordinates[0]);
-            location.setY(disCoordinates[1]);
-            location.setZ(disCoordinates[2]);
-            System.out.println("lat, lon:" + lat + ", " + lon);
-            System.out.println("DIS coord:" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
-
-            // Optionally, we can do some rotation of the entity
-            /*
-            Orientation orientation = espdu.getEntityOrientation();
-            float psi = orientation.getPsi();
-            psi = psi + idx;
-            orientation.setPsi(psi);
-            orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
-             */
-            
-            // You can set other ESPDU values here, such as the velocity, acceleration,
-            // and so on.
-
-            // Marshal out the espdu object to a byte array, then send a datagram
-            // packet with that data in it.
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            DataOutputStream dos = new DataOutputStream(baos);
-            espdu.marshal(dos);
-
-            FirePdu fire = new FirePdu();
-            byte[] fireArray = fire.marshal();
-            
-            // The byte array here is the packet in DIS format. We put that into a 
-            // datagram and send it.
-            byte[] data = baos.toByteArray();
-
-            bcastAddresses = getBroadcastAddresses();
-            Iterator it = bcastAddresses.iterator();
-            while(it.hasNext())
-            {
-               InetAddress bcast = (InetAddress)it.next();
-               System.out.println("Sending bcast to " + bcast);
-               DatagramPacket packet = new DatagramPacket(data, data.length, bcast, 3000);
-               socket.send(packet);
-               packet = new DatagramPacket(fireArray, fireArray.length, bcast, 3000);
-               //socket.send(packet);
-            }
-            
-            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
-            Thread.sleep(3000);
-
-            location = espdu.getEntityLocation();
-            
-            System.out.println("Espdu #" + idx + " EID=[" + eid.getSite() + "," + eid.getApplication() + "," + eid.getEntity() + "]");
-            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
-            double c[] = {location.getX(), location.getY(), location.getZ()};
-            double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
-//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
-
-        }
-    }
-    catch(Exception e)
-    {
-        System.out.println(e);
-    }
-        
-}
-
- /**
-    * A number of sites get all snippy about using 255.255.255.255 for a bcast
-    * address; it trips their security software and they kick you off their 
-    * network. (Comcast, NPS.) This determines the bcast address for all
-    * connected interfaces, based on the IP and subnet mask. If you have
-    * a dual-homed host it will return a bcast address for both. If you have
-    * some VMs running on your host this will pick up the addresses for those
-    * as well--eg running VMWare on your laptop with a local IP this will
-    * also pick up a 192.168 address assigned to the VM by the host OS.
-    * 
-    * @return set of all bcast addresses
-    */
-   public static Set<InetAddress> getBroadcastAddresses()
-   {
-       Set<InetAddress> bcastAddresses = new HashSet<InetAddress>();
-       Enumeration interfaces;
-       
-       try
-       {
-           interfaces = NetworkInterface.getNetworkInterfaces();
-           
-           while(interfaces.hasMoreElements())
-           {
-               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
-               
-               if(anInterface.isUp())
-               {
-                   Iterator it = anInterface.getInterfaceAddresses().iterator();
-                   while(it.hasNext())
-                   {
-                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
-                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
-                           continue;
-                       
-                       //System.out.println("Getting bcast address for " + anAddress);
-                       InetAddress abcast = anAddress.getBroadcast();
-                       if(abcast != null)
-                        bcastAddresses.add(abcast);
-                   }
-               }
-           }
-           
-       }
-       catch(Exception e)
-       {
-           e.printStackTrace();
-           System.out.println(e);
-       }
-       
-       return bcastAddresses;   
-   }
-
-}
+// package edu.nps.moves.examples; // copy example from OpenDIS distribution, modify to serve as template
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import edu.nps.moves.dis.*;
+import edu.nps.moves.disutil.DisTime;
+
+/**
+ * Creates and sends ESPDUs in IEEE binary format. 
+ *
+ * @author DMcG
+ */
+public class Sasala_OpenDisEspduSender1 
+{
+    public static final int NUMBER_TO_SEND = 5000;
+
+    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
+
+    /** Default multicast group address we send on */
+    public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
+   
+    /** Default port we send on */
+    public static final int    DIS_DESTINATION_PORT = 3000;
+    
+/** Possible system properties, passed in via -Dattr=val
+     * networkMode: unicast, broadcast, multicast
+     * destinationIp: where to send the packet. If in multicast mode, this can be multicast.
+     *                To determine broadcast destination IP, use an online broadcast address
+     *                calculator, for example http://www.remotemonitoringsystems.ca/broadcast.php
+     *                If in multicast mode, a join() will be done on the multicast address.
+     * port: port used for both source and destination.
+     * @param args 
+     */
+public static void main(String args[])
+{
+    /** an entity state pdu */
+    EntityStatePdu espdu = new EntityStatePdu();
+    MulticastSocket socket = null; // must be initialized, even if null
+    DisTime disTime = DisTime.getInstance(); // TODO explain
+    int alternator = -1;
+    
+    // ICBM coordinates for my office
+    double radians = 0;
+    
+    // Default settings. These are used if no system properties are set. 
+    // If system properties are passed in, these are over ridden.
+    int port = DIS_DESTINATION_PORT;
+    NetworkMode mode = NetworkMode.BROADCAST;
+    InetAddress destinationIp = null; // must be initialized, even if null
+    
+    try
+    {
+        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
+    }
+    catch(UnknownHostException e)
+    {
+        System.out.println(e + " Cannot create multicast address");
+        System.exit(0);
+    }
+    
+    // All system properties, passed in on the command line via -Dattribute=value
+    Properties systemProperties = System.getProperties();
+    
+    // IP address we send to
+    String destinationIpString = systemProperties.getProperty("destinationIp");
+    
+    // Port we send to, and local port we open the socket on
+    String portString = systemProperties.getProperty("port");
+    
+    // Network mode: unicast, multicast, broadcast
+    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
+        
+    // Set up a socket to send information
+    try
+    {
+        // Port we send to
+        if(portString != null)
+            port = Integer.parseInt(portString);
+        
+        socket = new MulticastSocket(port);
+        
+        // Where we send packets to, the destination IP address
+        if(destinationIpString != null)
+        {
+            destinationIp = InetAddress.getByName(destinationIpString);
+        }
+
+        // Type of transport: unicast, broadcast, or multicast
+		// TODO convert to String constants
+        if(networkModeString != null)
+        {
+            if(networkModeString.equalsIgnoreCase("unicast"))
+                mode = NetworkMode.UNICAST;
+            else if(networkModeString.equalsIgnoreCase("broadcast"))
+                mode = NetworkMode.BROADCAST;
+            else if(networkModeString.equalsIgnoreCase("multicast"))
+            {
+                mode = NetworkMode.MULTICAST;
+                if(!destinationIp.isMulticastAddress())
+                {
+                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
+                }
+                
+                socket.joinGroup(destinationIp);
+            }
+        } // end networkModeString
+    }
+    catch(IOException | RuntimeException e)
+    {
+        System.out.println("Unable to initialize networking. Exiting.");
+        System.out.println(e);
+        System.exit(-1);
+    }
+    
+    // Initialize values in the Entity State PDU object. The exercise ID is 
+    // a way to differentiate between different virtual worlds on one network.
+    // Note that some values (such as the PDU type and PDU family) are set
+    // automatically when you create the ESPDU.
+    espdu.setExerciseID((short)1);
+    
+    // The EID is the unique identifier for objects in the world. This 
+    // EID should match up with the ID for the object specified in the 
+    // VMRL/x3d/virtual world.
+    EntityID entityID = espdu.getEntityID();
+    entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
+    entityID.setApplication(1); 
+    entityID.setEntity(2); 
+    
+    // Set the entity type. SISO has a big list of enumerations, so that by
+    // specifying various numbers we can say this is an M1A2 American tank,
+    // the USS Enterprise, and so on. We'll make this a tank. There is a 
+    // separate project elsehwhere in this project that implements DIS 
+    // enumerations in C++ and Java, but to keep things simple we just use
+    // numbers here.
+    EntityType entityType = espdu.getEntityType();
+    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
+    entityType.setCountry(225);              // USA
+    entityType.setDomain((short)1);          // Land (vs air, surface, subsurface, space)
+    entityType.setCategory((short)1);        // Tank
+    entityType.setSubcategory((short)1);     // M1 Abrams
+    entityType.setSpec((short)3);            // M1A2 Abrams
+ 
+    Set<InetAddress> broadcastAddresses;
+    // Loop through sending N ESPDUs
+    try
+    {
+        System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
+        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
+        {
+            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
+            // hour, and time is set to DIS time units from the top of the hour. 
+            // This means that if you start sending just before the top of the hour
+            // the time units can roll over to zero as you are sending. The receivers
+            // (escpecially homegrown ones) are often not able to detect rollover
+            // and may start discarding packets as dupes or out of order. We use
+            // an NPS timestamp here, hundredths of a second since the start of the
+            // year. The DIS standard for time is often ignored in the wild; I've seen
+            // people use Unix time (seconds since 1970) and more. Or you can
+            // just stuff idx into the timestamp field to get something that is monotonically
+            // increasing.
+            
+            // Note that timestamp is used to detect duplicate and out of order packets. 
+            // That means if you DON'T change the timestamp, many implementations will simply
+            // discard subsequent packets that have an identical timestamp. Also, if they
+            // receive a PDU with an timestamp lower than the last one they received, they
+            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
+            // update the timestamp on ALL packets sent.
+            
+
+            // An alterative approach: actually follow the standard. It's a crazy concept,
+            // but it might just work.
+            int timestamp = disTime.getDisAbsoluteTimestamp();
+            espdu.setTimestamp(timestamp);
+            
+            // Set the position of the entity in the world. DIS uses a cartesian 
+            // coordinate system with the origin at the center of the earth, the x
+            // axis out at the equator and prime meridian, y out at the equator and
+            // 90 deg east, and z up and out the north pole. To place an object on
+            // the earth's surface you also need a model for the shape of the earth
+            // (it's not a sphere.) All the fancy math necessary to do this is in
+            // the SEDRIS SRM package. There are also some one-off formulas for 
+            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
+            // Here we use those one-off formulas.
+        
+            radians = (radians + (Math.PI/6)) % (2*Math.PI);
+       
+            Vector3Double location = espdu.getEntityLocation();
+            location.setX(Math.cos(radians)*1000);
+            location.setY(Math.sin(radians)*1000);
+            location.setZ(250);
+            
+            // Optionally, we can do some rotation of the entity
+            
+            Orientation orientation = espdu.getEntityOrientation();
+            orientation.setTheta((float)(radians + (Math.PI/2))%(float)(Math.PI *2));
+            
+            // You can set other ESPDU values here, such as the velocity, acceleration,
+            // and so on.
+
+            // Marshal out the espdu object to a byte array, then send a datagram
+            // packet with that data in it.
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            DataOutputStream dos = new DataOutputStream(baos);
+            espdu.marshal(dos);
+
+            FirePdu fire = new FirePdu();
+            byte[] fireArray = fire.marshal();
+            
+            // The byte array here is the packet in DIS format. We put that into a 
+            // datagram and send it.
+            byte[] data = baos.toByteArray();
+
+            broadcastAddresses = getBroadcastAddresses();
+            Iterator it = broadcastAddresses.iterator();
+            while(it.hasNext())
+            {
+               InetAddress broadcast = (InetAddress)it.next();
+               System.out.println("Sending broadcast datagram packet to " + broadcast);
+               DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, 3000);
+               socket.send(packet);
+			   // TODO experiment with these!  8)
+               packet = new DatagramPacket(fireArray, fireArray.length, broadcast, 3000); // alternate
+               socket.send(packet);
+            }
+            
+            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
+            Thread.sleep(3000);
+            location = espdu.getEntityLocation();  
+            System.out.println("Espdu #" + idx + " EID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
+            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
+            System.out.println(" Orientation: " + orientation.getTheta());
+            //System.out.println(" Location (lat/lon/alt): [" + lat + ", " + lla[1] + ", " + lla[2] + "]");
+
+        }
+    }
+    catch(IOException | InterruptedException e)
+    {
+        System.out.println(e);
+    }
+        
+}
+
+ /**
+    * A number of sites get all snippy about using 255.255.255.255 for a broadcast
+    * address; it trips their security software and they kick you off their 
+    * network. (Comcast, NPS.) This determines the broadcast address for all
+    * connected interfaces, based on the IP and subnet mask. If you have
+    * a dual-homed host it will return a broadcast address for both. If you have
+    * some VMs running on your host this will pick up the addresses for those
+    * as well--eg running VMWare on your laptop with a local IP this will
+    * also pick up a 192.168 address assigned to the VM by the host OS.
+    * 
+    * @return set of all broadcast addresses
+    */
+   public static Set<InetAddress> getBroadcastAddresses()
+   {
+       Set<InetAddress> broadcastAddresses = new HashSet<>();
+       Enumeration interfaces;
+       
+       try
+       {
+           interfaces = NetworkInterface.getNetworkInterfaces();
+           
+           while(interfaces.hasMoreElements())
+           {
+               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
+               
+               if(anInterface.isUp())
+               {
+                   Iterator it = anInterface.getInterfaceAddresses().iterator();
+                   while(it.hasNext())
+                   {
+                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
+                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
+                           continue;
+                       
+                       //System.out.println("Getting broadcast address for " + anAddress);
+                       InetAddress broadcastAddress = anAddress.getBroadcast();
+                       if(broadcastAddress != null)
+                          broadcastAddresses.add(broadcastAddress);
+                   }
+               }
+           }
+           
+       }
+       catch(SocketException e)
+       {
+           e.printStackTrace();
+           System.out.println(e);
+       }
+       
+       return broadcastAddresses;   
+   }
+
+}
diff --git a/projects/Assignments/homework3/Sasala_README.md b/projects/Assignments/homework3/Sasala_README.md
new file mode 100644
index 0000000000000000000000000000000000000000..9e62214da8776261af2c6cbc52a43e50e31b8041
--- /dev/null
+++ b/projects/Assignments/homework3/Sasala_README.md
@@ -0,0 +1,29 @@
+## Homework Assignment 3 Checklist
+
+1. [x] Add X3D-Edit as Netbeans Plugin from https://savage.nps.edu/X3D-Edit/#Downloads
+
+2. [x] Optional: checkout Open-DIS-Java library source from https://github.com/open-dis/open-dis-java
+
+3. [x] Otherwise just inspect files of interest from
+   [edu.nps.moves.examples](https://github.com/open-dis/open-dis-java/tree/master/src/main/java/edu/nps/moves/examples)
+
+4. [x] Copy README.md and create YournameREADME.md documentation file...
+
+5. [x] Plan a track of interest - entity travels in a circle and changes heading(orientation) correspondingly 
+
+6. [x] Copy, then Refactor/Rename example file OpenDisEspduSender.java or OpenDisPduSender.java as YourNameSomething.java
+
+7. [x] Modify your example file to produce track PDUs (and be cool)
+
+8. [x] Generate PDUs...
+
+9. [x] Test PDU reading using Wireshark...example below (see also screenshot file)
+
+835	46.316530	172.20.155.227	172.20.159.255	DIS	186	PDUType: 1 	 Entity State, Platform, Land, (1:1:2)
+799	43.208823	172.20.155.227	172.20.159.255	DIS	186	PDUType: 1 	 Entity State, Platform, Land, (1:1:2)
+722	40.094776	172.20.155.227	172.20.159.255	DIS	186	PDUType: 1 	 Entity State, Platform, Land, (1:1:2)
+631	37.026221	172.20.155.227	172.20.159.255	DIS	186	PDUType: 1 	 Entity State, Platform, Land, (1:1:2)
+
+10. [x] Record PDU file using X3D-Edit...
+
+11. [x] Playback PDU file using X3D-Edit...
diff --git a/projects/Assignments/homework3/ABEspduSenderB.java b/projects/Assignments/homework3/Tackett_Assignment3_OpenDisEspduSender.java
similarity index 68%
rename from projects/Assignments/homework3/ABEspduSenderB.java
rename to projects/Assignments/homework3/Tackett_Assignment3_OpenDisEspduSender.java
index 4e373aa924a7f4c957fd198a2f9b7717b664ba95..77c018cd07ea1cb93e741e158e1e317492257075 100644
--- a/projects/Assignments/homework3/ABEspduSenderB.java
+++ b/projects/Assignments/homework3/Tackett_Assignment3_OpenDisEspduSender.java
@@ -1,323 +1,369 @@
-
-
-import java.io.*;
-import java.net.*;
-import java.util.*;
-
-import edu.nps.moves.dis.*;
-import edu.nps.moves.disutil.CoordinateConversions;
-import edu.nps.moves.disutil.DisTime;
-
-/**
- * Creates and sends ESPDUs in IEEE binary format. 
- *
- * @author DMcG
- */
-public class ABEspduSenderB 
-{
-    public static final int NUMBER_TO_SEND = 5000;
-
-    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
-
-    /** default multicast group we send on */
-    public static final String DEFAULT_MULTICAST_GROUP = "239.1.2.3";
-   
-    /** Port we send on */
-    public static final int    DIS_DESTINATION_PORT = 3000;
-    
-/** Possible system properties, passed in via -Dattr=val
-     * networkMode: unicast, broadcast, multicast
-     * destinationIp: where to send the packet. If in multicast mode, this can be mcast.
-     *                To determine bcast destination IP, use an online bcast address
-     *                caclulator, for example http://www.remotemonitoringsystems.ca/broadcast.php
-     *                If in mcast mode, a join() will be done on the mcast address.
-     * port: port used for both source and destination.
-     * @param args 
-     */
-public static void main(String args[])
-{
-    /** an entity state pdu */
-    EntityStatePdu espdu = new EntityStatePdu();
-    MulticastSocket socket = null;
-    DisTime disTime = DisTime.getInstance();
-    int alternator = -1;
-    
-    // ICBM coordinates for my office
-    double lat = 36.595517; 
-    double lon = -121.877000;
-
-    
-    // Default settings. These are used if no system properties are set. 
-    // If system properties are passed in, these are over ridden.
-    int port = DIS_DESTINATION_PORT;
-    NetworkMode mode = NetworkMode.MULTICAST;
-    InetAddress destinationIp = null;
-    
-    try
-    {
-        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
-    }
-    catch(Exception e)
-    {
-        System.out.println(e + " Cannot create multicast address");
-        System.exit(0);
-    }
-    
-    // All system properties, passed in on the command line via -Dattribute=value
-    Properties systemProperties = System.getProperties();
-    
-    // IP address we send to
-    String destinationIpString = systemProperties.getProperty("destinationIp");
-    
-    // Port we send to, and local port we open the socket on
-    String portString = systemProperties.getProperty("port");
-    
-    // Network mode: unicast, multicast, broadcast
-    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
-        
-
-    // Set up a socket to send information
-    try
-    {
-        // Port we send to
-        if(portString != null)
-            port = Integer.parseInt(portString);
-        
-        socket = new MulticastSocket(port);
-        
-        // Where we send packets to, the destination IP address
-        if(destinationIpString != null)
-        {
-            destinationIp = InetAddress.getByName(destinationIpString);
-        }
-
-        // Type of transport: unicast, broadcast, or multicast
-        if(networkModeString != null)
-        {
-            if(networkModeString.equalsIgnoreCase("unicast"))
-                mode = NetworkMode.UNICAST;
-            else if(networkModeString.equalsIgnoreCase("broadcast"))
-                mode = NetworkMode.BROADCAST;
-            else if(networkModeString.equalsIgnoreCase("multicast"))
-            {
-                mode = NetworkMode.MULTICAST;
-                if(!destinationIp.isMulticastAddress())
-                {
-                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
-                }
-                
-                socket.joinGroup(destinationIp);
-                
-            }
-        } // end networkModeString
-    }
-    catch(Exception e)
-    {
-        System.out.println("Unable to initialize networking. Exiting.");
-        System.out.println(e);
-        System.exit(-1);
-    }
-    
-    // Initialize values in the Entity State PDU object. The exercise ID is 
-    // a way to differentiate between different virtual worlds on one network.
-    // Note that some values (such as the PDU type and PDU family) are set
-    // automatically when you create the ESPDU.
-    espdu.setExerciseID((short)1);
-    
-    // The EID is the unique identifier for objects in the world. This 
-    // EID should match up with the ID for the object specified in the 
-    // VMRL/x3d/virtual world.
-    EntityID eid = espdu.getEntityID();
-    eid.setSite(1);  // 0 is apparently not a valid site number, per the spec
-    eid.setApplication(1); 
-    eid.setEntity(2); 
-    
-    // Set the entity type. SISO has a big list of enumerations, so that by
-    // specifying various numbers we can say this is an M1A2 American tank,
-    // the USS Enterprise, and so on. We'll make this a tank. There is a 
-    // separate project elsehwhere in this project that implements DIS 
-    // enumerations in C++ and Java, but to keep things simple we just use
-    // numbers here.
-    EntityType entityType = espdu.getEntityType();
-    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
-    entityType.setCountry(225);              // USA
-    entityType.setDomain((short)1);          // Land (vs air, surface, subsurface, space)
-    entityType.setCategory((short)1);        // Tank
-    entityType.setSubcategory((short)1);     // M1 Abrams
-    entityType.setSpec((short)3);            // M1A2 Abrams
-    
-
-    Set<InetAddress> bcastAddresses = getBroadcastAddresses();
-    // Loop through sending N ESPDUs
-    try
-    {
-        System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
-        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
-        {
-            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
-            // hour, and time is set to DIS time units from the top of the hour. 
-            // This means that if you start sending just before the top of the hour
-            // the time units can roll over to zero as you are sending. The receivers
-            // (escpecially homegrown ones) are often not able to detect rollover
-            // and may start discarding packets as dupes or out of order. We use
-            // an NPS timestamp here, hundredths of a second since the start of the
-            // year. The DIS standard for time is often ignored in the wild; I've seen
-            // people use Unix time (seconds since 1970) and more. Or you can
-            // just stuff idx into the timestamp field to get something that is monotonically
-            // increasing.
-            
-            // Note that timestamp is used to detect duplicate and out of order packets. 
-            // That means if you DON'T change the timestamp, many implementations will simply
-            // discard subsequent packets that have an identical timestamp. Also, if they
-            // receive a PDU with an timestamp lower than the last one they received, they
-            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
-            // update the timestamp on ALL packets sent.
-            
-
-            // An alterative approach: actually follow the standard. It's a crazy concept,
-            // but it might just work.
-            int ts = disTime.getDisAbsoluteTimestamp();
-            espdu.setTimestamp(ts);
-            
-            // Set the position of the entity in the world. DIS uses a cartesian 
-            // coordinate system with the origin at the center of the earth, the x
-            // axis out at the equator and prime meridian, y out at the equator and
-            // 90 deg east, and z up and out the north pole. To place an object on
-            // the earth's surface you also need a model for the shape of the earth
-            // (it's not a sphere.) All the fancy math necessary to do this is in
-            // the SEDRIS SRM package. There are also some one-off formulas for 
-            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
-            // Here we use those one-off formulas.
-
-            // Modify the position of the object. This will send the object a little
-            // due east by adding some to the longitude every iteration. Since we
-            // are on the Pacific coast, this sends the object east. Assume we are
-            // at zero altitude. In other worlds you'd use DTED to determine the
-            // local ground altitude at that lat/lon, or you'd just use ground clamping.
-            // The x and y values will change, but the z value should not.
-            
-            //lon = lon + (double)((double)idx / 100000.0);
-            //System.out.println("lla=" + lat + "," + lon + ", 0.0");
-
-            double direction = Math.pow((double)(-1.0), (double)(idx));
-            lon = lon + (direction * 0.00006);
-            System.out.println(lon);
-            
-            double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
-            Vector3Double location = espdu.getEntityLocation();
-            location.setX(disCoordinates[0]);
-            location.setY(disCoordinates[1]);
-            location.setZ(disCoordinates[2]);
-            System.out.println("lat, lon:" + lat + ", " + lon);
-            System.out.println("DIS coord:" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
-
-            // Optionally, we can do some rotation of the entity
-            /*
-            Orientation orientation = espdu.getEntityOrientation();
-            float psi = orientation.getPsi();
-            psi = psi + idx;
-            orientation.setPsi(psi);
-            orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
-             */
-            
-            // You can set other ESPDU values here, such as the velocity, acceleration,
-            // and so on.
-
-            // Marshal out the espdu object to a byte array, then send a datagram
-            // packet with that data in it.
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
-            DataOutputStream dos = new DataOutputStream(baos);
-            espdu.marshal(dos);
-
-            FirePdu fire = new FirePdu();
-            byte[] fireArray = fire.marshal();
-            
-            // The byte array here is the packet in DIS format. We put that into a 
-            // datagram and send it.
-            byte[] data = baos.toByteArray();
-
-            bcastAddresses = getBroadcastAddresses();
-            Iterator it = bcastAddresses.iterator();
-            while(it.hasNext())
-            {
-               InetAddress bcast = (InetAddress)it.next();
-               System.out.println("Sending bcast to " + bcast);
-               DatagramPacket packet = new DatagramPacket(data, data.length, bcast, 3000);
-               socket.send(packet);
-               packet = new DatagramPacket(fireArray, fireArray.length, bcast, 3000);
-               //socket.send(packet);
-            }
-            
-            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
-            Thread.sleep(3000);
-
-            location = espdu.getEntityLocation();
-            
-            System.out.println("Espdu #" + idx + " EID=[" + eid.getSite() + "," + eid.getApplication() + "," + eid.getEntity() + "]");
-            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
-            double c[] = {location.getX(), location.getY(), location.getZ()};
-            double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
-//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
-
-        }
-    }
-    catch(Exception e)
-    {
-        System.out.println(e);
-    }
-        
-}
-
- /**
-    * A number of sites get all snippy about using 255.255.255.255 for a bcast
-    * address; it trips their security software and they kick you off their 
-    * network. (Comcast, NPS.) This determines the bcast address for all
-    * connected interfaces, based on the IP and subnet mask. If you have
-    * a dual-homed host it will return a bcast address for both. If you have
-    * some VMs running on your host this will pick up the addresses for those
-    * as well--eg running VMWare on your laptop with a local IP this will
-    * also pick up a 192.168 address assigned to the VM by the host OS.
-    * 
-    * @return set of all bcast addresses
-    */
-   public static Set<InetAddress> getBroadcastAddresses()
-   {
-       Set<InetAddress> bcastAddresses = new HashSet<InetAddress>();
-       Enumeration interfaces;
-       
-       try
-       {
-           interfaces = NetworkInterface.getNetworkInterfaces();
-           
-           while(interfaces.hasMoreElements())
-           {
-               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
-               
-               if(anInterface.isUp())
-               {
-                   Iterator it = anInterface.getInterfaceAddresses().iterator();
-                   while(it.hasNext())
-                   {
-                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
-                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
-                           continue;
-                       
-                       //System.out.println("Getting bcast address for " + anAddress);
-                       InetAddress abcast = anAddress.getBroadcast();
-                       if(abcast != null)
-                        bcastAddresses.add(abcast);
-                   }
-               }
-           }
-           
-       }
-       catch(Exception e)
-       {
-           e.printStackTrace();
-           System.out.println(e);
-       }
-       
-       return bcastAddresses;   
-   }
-
-}
+// package edu.nps.moves.examples; // copy example from OpenDIS distribution, modify to serve as template
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import edu.nps.moves.dis.*;
+import edu.nps.moves.disutil.CoordinateConversions;
+import edu.nps.moves.disutil.DisTime;
+
+/**
+ * Creates and sends ESPDUs in IEEE binary format. 
+ *
+ * @author DMcG
+ */
+public class Tackett_Assignment3_OpenDisEspduSender 
+{
+    public static final int NUMBER_TO_SEND = 10;
+
+    public enum NetworkMode{UNICAST, MULTICAST, BROADCAST};
+
+    /** Default multicast group address we send on */
+    public static final String DEFAULT_MULTICAST_GROUP="239.1.2.3";
+   
+    /** Default port we send on */
+    public static final int    DIS_DESTINATION_PORT = 3000;
+    
+    private static final ArrayList <Float[]> track_coordinates = new ArrayList<>();
+    
+/** Possible system properties, passed in via -Dattr=val
+     * networkMode: unicast, broadcast, multicast
+     * destinationIp: where to send the packet. If in multicast mode, this can be multicast.
+     *                To determine broadcast destination IP, use an online broadcast address
+     *                calculator, for example http://www.remotemonitoringsystems.ca/broadcast.php
+     *                If in multicast mode, a join() will be done on the multicast address.
+     * port: port used for both source and destination.
+     * @param args 
+     */
+public static void main(String args[])
+{
+    /** an entity state pdu */
+    EntityStatePdu espdu = new EntityStatePdu();
+    MulticastSocket socket = null; // must be initialized, even if null
+    DisTime disTime = DisTime.getInstance(); // TODO explain
+    int alternator = -1;
+    
+    // Lat/Lon coordinates 
+//    double lat = 36.616366; 
+//    double lon = -121.913065;
+    
+    // Default settings. These are used if no system properties are set. 
+    // If system properties are passed in, these are over ridden.
+    int port = DIS_DESTINATION_PORT;
+    NetworkMode mode = NetworkMode.BROADCAST;
+    InetAddress destinationIp = null; // must be initialized, even if null
+    
+    try
+    {
+        destinationIp = InetAddress.getByName(DEFAULT_MULTICAST_GROUP);
+    }
+    catch(UnknownHostException e)
+    {
+        System.out.println(e + " Cannot create multicast address");
+        System.exit(0);
+    }
+    
+    // All system properties, passed in on the command line via -Dattribute=value
+    Properties systemProperties = System.getProperties();
+    
+    // IP address we send to
+    String destinationIpString = systemProperties.getProperty("destinationIp");
+    
+    // Port we send to, and local port we open the socket on
+    String portString = systemProperties.getProperty("port");
+    
+    // Network mode: unicast, multicast, broadcast
+    String networkModeString = systemProperties.getProperty("networkMode"); // unicast or multicast or broadcast
+        
+    // Set up a socket to send information
+    try
+    {
+        // Port we send to
+        if(portString != null)
+            port = Integer.parseInt(portString);
+        
+        socket = new MulticastSocket(port);
+        
+        // Where we send packets to, the destination IP address
+        if(destinationIpString != null)
+        {
+            destinationIp = InetAddress.getByName(destinationIpString);
+        }
+
+        // Type of transport: unicast, broadcast, or multicast
+		// TODO convert to String constants
+        if(networkModeString != null)
+        {
+            if(networkModeString.equalsIgnoreCase("unicast"))
+                mode = NetworkMode.UNICAST;
+            else if(networkModeString.equalsIgnoreCase("broadcast"))
+                mode = NetworkMode.BROADCAST;
+            else if(networkModeString.equalsIgnoreCase("multicast"))
+            {
+                mode = NetworkMode.MULTICAST;
+                if(!destinationIp.isMulticastAddress())
+                {
+                    throw new RuntimeException("Sending to multicast address, but destination address " + destinationIp.toString() + "is not multicast");
+                }
+                
+                socket.joinGroup(destinationIp);
+            }
+        } // end networkModeString
+    }
+    catch(IOException | RuntimeException e)
+    {
+        System.out.println("Unable to initialize networking. Exiting.");
+        System.out.println(e);
+        System.exit(-1);
+    }
+    
+    // Initialize values in the Entity State PDU object. The exercise ID is 
+    // a way to differentiate between different virtual worlds on one network.
+    // Note that some values (such as the PDU type and PDU family) are set
+    // automatically when you create the ESPDU.
+    espdu.setExerciseID((short)1);
+    
+    // The EID is the unique identifier for objects in the world. This 
+    // EID should match up with the ID for the object specified in the 
+    // VMRL/x3d/virtual world.
+    EntityID entityID = espdu.getEntityID();
+    entityID.setSite(1);  // 0 is apparently not a valid site number, per the spec
+    entityID.setApplication(1); 
+    entityID.setEntity(2); 
+    
+    // Set the entity type. SISO has a big list of enumerations, so that by
+    // specifying various numbers we can say this is an M1A2 American tank,
+    // the USS Enterprise, and so on. We'll make this a tank. There is a 
+    // separate project elsehwhere in this project that implements DIS 
+    // enumerations in C++ and Java, but to keep things simple we just use
+    // numbers here.
+    EntityType entityType = espdu.getEntityType();
+    entityType.setEntityKind((short)1);      // Platform (vs lifeform, munition, sensor, etc.)
+    entityType.setCountry(225);              // USA
+    entityType.setDomain((short)1);          // Land (vs air, surface, subsurface, space)
+    entityType.setCategory((short)1);        // Tank
+    entityType.setSubcategory((short)1);     // M1 Abrams
+    entityType.setSpec((short)3);            // M1A2 Abrams
+    
+
+    Set<InetAddress> broadcastAddresses;
+    // Loop through sending N ESPDUs
+    try
+    {
+                Float[] TrackCoor1 = new Float [2];
+        TrackCoor1[0] = 36.585657f;
+        TrackCoor1[1] = -121.879920f;
+        track_coordinates.add(TrackCoor1);
+        Float[] TrackCoor2 = new Float [2];
+        TrackCoor2[0] = 36.584853f;
+        TrackCoor2[1] = -121.880024f;
+        track_coordinates.add(TrackCoor2);
+        Float[] TrackCoor3 = new Float [2];
+        TrackCoor3[0] = 36.583500f;
+        TrackCoor3[1] = -121.879615f;
+        track_coordinates.add(TrackCoor3);
+        Float[] TrackCoor4 = new Float [2];
+        TrackCoor4[0] = 36.586307f;
+        TrackCoor4[1] = -121.874582f;
+        track_coordinates.add(TrackCoor4);
+        Float[] TrackCoor5 = new Float [2];
+        TrackCoor5[0] = 36.588670f;
+        TrackCoor5[1] = -121.877928f;
+        track_coordinates.add(TrackCoor5);
+        Float[] TrackCoor6 = new Float [2];
+        TrackCoor6[0] = 36.591124f;
+        TrackCoor6[1] = -121.880074f;
+        track_coordinates.add(TrackCoor6);
+        Float[] TrackCoor7 = new Float [2];
+        TrackCoor7[0] = 36.592827f;
+        TrackCoor7[1] = -121.877149f;
+        track_coordinates.add(TrackCoor7);
+        Float[] TrackCoor8 = new Float [2];
+        TrackCoor8[0] = 36.594051f;
+        TrackCoor8[1] = -121.877452f;
+        track_coordinates.add(TrackCoor8);
+        Float[] TrackCoor9 = new Float [2];
+        TrackCoor9[0] = 36.594245f;
+        TrackCoor9[1] = -121.876477f;
+        track_coordinates.add(TrackCoor9);
+        Float[] TrackCoor10 = new Float [2];
+        TrackCoor10[0] = 36.595230f;
+        TrackCoor10[1] = -121.877537f;
+        track_coordinates.add(TrackCoor10);
+        
+        //System.out.println("Sending " + NUMBER_TO_SEND + " ESPDU packets to " + destinationIp.toString());
+        for(int idx = 0; idx < NUMBER_TO_SEND; idx++)
+        {
+            System.out.println("Sending espdu packet" + idx + " to " + destinationIp.toString());
+            // DIS time is a pain in the ass. DIS time units are 2^31-1 units per
+            // hour, and time is set to DIS time units from the top of the hour. 
+            // This means that if you start sending just before the top of the hour
+            // the time units can roll over to zero as you are sending. The receivers
+            // (escpecially homegrown ones) are often not able to detect rollover
+            // and may start discarding packets as dupes or out of order. We use
+            // an NPS timestamp here, hundredths of a second since the start of the
+            // year. The DIS standard for time is often ignored in the wild; I've seen
+            // people use Unix time (seconds since 1970) and more. Or you can
+            // just stuff idx into the timestamp field to get something that is monotonically
+            // increasing.
+            
+            // Note that timestamp is used to detect duplicate and out of order packets. 
+            // That means if you DON'T change the timestamp, many implementations will simply
+            // discard subsequent packets that have an identical timestamp. Also, if they
+            // receive a PDU with an timestamp lower than the last one they received, they
+            // may discard it as an earlier, out-of-order PDU. So it is a good idea to
+            // update the timestamp on ALL packets sent.
+            
+
+            // An alterative approach: actually follow the standard. It's a crazy concept,
+            // but it might just work.
+            int timestamp = disTime.getDisAbsoluteTimestamp();
+            espdu.setTimestamp(timestamp);
+            
+            // Set the position of the entity in the world. DIS uses a cartesian 
+            // coordinate system with the origin at the center of the earth, the x
+            // axis out at the equator and prime meridian, y out at the equator and
+            // 90 deg east, and z up and out the north pole. To place an object on
+            // the earth's surface you also need a model for the shape of the earth
+            // (it's not a sphere.) All the fancy math necessary to do this is in
+            // the SEDRIS SRM package. There are also some one-off formulas for 
+            // doing conversions from, for example, lat/lon/altitude to DIS coordinates.
+            // Here we use those one-off formulas.
+
+            // Modify the position of the object. This will send the object a little
+            // due east by adding some to the longitude every iteration. Since we
+            // are on the Pacific coast, this sends the object east. Assume we are
+            // at zero altitude. In other worlds you'd use DTED to determine the
+            // local ground altitude at that lat/lon, or you'd just use ground clamping.
+            // The x and y values will change, but the z value should not.
+            
+            //lon = lon + (double)((double)idx / 100000.0);
+            //System.out.println("lla=" + lat + "," + lon + ", 0.0");
+
+//            double direction = Math.pow((double)(-1.0), (double)(idx));
+//            lon = lon + (direction * 0.00006);
+//            System.out.println(lon);
+
+            Float lat = track_coordinates.get(idx)[0];
+            Float lon = track_coordinates.get(idx)[1];
+            
+            double disCoordinates[] = CoordinateConversions.getXYZfromLatLonDegrees(lat, lon, 1.0);
+            Vector3Double location = espdu.getEntityLocation();
+            location.setX(disCoordinates[0]);
+            location.setY(disCoordinates[1]);
+            location.setZ(disCoordinates[2]);
+            System.out.println("lat, lon:" + lat + ", " + lon);
+            System.out.println("DIS coord:" + disCoordinates[0] + ", " + disCoordinates[1] + ", " + disCoordinates[2]);
+
+            // Optionally, we can do some rotation of the entity
+            /*
+            Orientation orientation = espdu.getEntityOrientation();
+            float psi = orientation.getPsi();
+            psi = psi + idx;
+            orientation.setPsi(psi);
+            orientation.setTheta((float)(orientation.getTheta() + idx /2.0));
+             */
+            
+            // You can set other ESPDU values here, such as the velocity, acceleration,
+            // and so on.
+
+            // Marshal out the espdu object to a byte array, then send a datagram
+            // packet with that data in it.
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            DataOutputStream dos = new DataOutputStream(baos);
+            espdu.marshal(dos);
+
+            FirePdu fire = new FirePdu();
+            byte[] fireArray = fire.marshal();
+            
+            // The byte array here is the packet in DIS format. We put that into a 
+            // datagram and send it.
+            byte[] data = baos.toByteArray();
+
+            broadcastAddresses = getBroadcastAddresses();
+            Iterator it = broadcastAddresses.iterator();
+            while(it.hasNext())
+            {
+               InetAddress broadcast = (InetAddress)it.next();
+               System.out.println("Sending broadcast datagram packet to " + broadcast);
+               DatagramPacket packet = new DatagramPacket(data, data.length, broadcast, 3000);
+               socket.send(packet);
+			   // TODO experiment with these!  8)
+//               packet = new DatagramPacket(fireArray, fireArray.length, broadcast, 3000); // alternate
+//               socket.send(packet);
+            }
+            
+            // Send every 1 sec. Otherwise this will be all over in a fraction of a second.
+            Thread.sleep(3000);
+
+            location = espdu.getEntityLocation();
+            
+            System.out.println("Espdu #" + idx + " EID=[" + entityID.getSite() + "," + entityID.getApplication() + "," + entityID.getEntity() + "]");
+            System.out.println(" DIS coordinates location=[" + location.getX() + "," + location.getY() + "," + location.getZ() + "]");
+            double c[] = {location.getX(), location.getY(), location.getZ()};
+            double lla[] = CoordinateConversions.xyzToLatLonDegrees(c);
+//            System.out.println(" Location (lat/lon/alt): [" + lla[0] + ", " + lla[1] + ", " + lla[2] + "]");
+
+        }
+    }
+    catch(IOException | InterruptedException e)
+    {
+        System.out.println(e);
+    }
+        
+}
+
+ /**
+    * A number of sites get all snippy about using 255.255.255.255 for a broadcast
+    * address; it trips their security software and they kick you off their 
+    * network. (Comcast, NPS.) This determines the broadcast address for all
+    * connected interfaces, based on the IP and subnet mask. If you have
+    * a dual-homed host it will return a broadcast address for both. If you have
+    * some VMs running on your host this will pick up the addresses for those
+    * as well--eg running VMWare on your laptop with a local IP this will
+    * also pick up a 192.168 address assigned to the VM by the host OS.
+    * 
+    * @return set of all broadcast addresses
+    */
+   public static Set<InetAddress> getBroadcastAddresses()
+   {
+       Set<InetAddress> broadcastAddresses = new HashSet<>();
+       Enumeration interfaces;
+       
+       try
+       {
+           interfaces = NetworkInterface.getNetworkInterfaces();
+           
+           while(interfaces.hasMoreElements())
+           {
+               NetworkInterface anInterface = (NetworkInterface)interfaces.nextElement();
+               
+               if(anInterface.isUp())
+               {
+                   Iterator it = anInterface.getInterfaceAddresses().iterator();
+                   while(it.hasNext())
+                   {
+                       InterfaceAddress anAddress = (InterfaceAddress)it.next();
+                       if((anAddress == null || anAddress.getAddress().isLinkLocalAddress()))
+                           continue;
+                       
+                       //System.out.println("Getting broadcast address for " + anAddress);
+                       InetAddress broadcastAddress = anAddress.getBroadcast();
+                       if(broadcastAddress != null)
+                          broadcastAddresses.add(broadcastAddress);
+                   }
+               }
+           }
+           
+       }
+       catch(SocketException e)
+       {
+           e.printStackTrace();
+           System.out.println(e);
+       }
+       
+       return broadcastAddresses;   
+   }
+
+}
diff --git a/projects/Assignments/homework3/Tackett_Assignment3_README b/projects/Assignments/homework3/Tackett_Assignment3_README
new file mode 100644
index 0000000000000000000000000000000000000000..ec5cbee9d81ee3b426d62ab3014fa17ff92a4a9f
--- /dev/null
+++ b/projects/Assignments/homework3/Tackett_Assignment3_README
@@ -0,0 +1,28 @@
+## Homework Assignment 3 Checklist
+
+1. [x] Add X3D-Edit as Netbeans Plugin from https://savage.nps.edu/X3D-Edit/#Downloads
+
+1. [x] Optional: checkout Open-DIS-Java library source from https://github.com/open-dis/open-dis-java
+
+1. [x] Otherwise just inspect files of interest from
+   [edu.nps.moves.examples](https://github.com/open-dis/open-dis-java/tree/master/src/main/java/edu/nps/moves/examples)
+
+1. [x] Copy README.md and create YournameREADME.md documentation file...
+
+1. [x] Plan a track of interest, described in YournameREADME.md documentation file...
+
+        Track of interest is a sample from a run route I did recently.
+
+1. [x] Copy, then Refactor/Rename example file OpenDisEspduSender.java or OpenDisPduSender.java as YourNameSomething.java
+
+1. [x] Modify your example file to produce track PDUs (and be cool)
+
+1. [x] Generate PDUs...
+
+1. [x] Test PDU reading using Wireshark...
+
+        IP address for my machine is 172.20.148.166
+
+1. [x] Record PDU file using X3D-Edit...
+
+1. [x] Playback PDU file using X3D-Edit...
diff --git a/projects/Assignments/homework3/Tackett_Wireshark.pcapng b/projects/Assignments/homework3/Tackett_Wireshark.pcapng
new file mode 100644
index 0000000000000000000000000000000000000000..6e0277a4267aa4f983d0b68438c1198e7674d99e
Binary files /dev/null and b/projects/Assignments/homework3/Tackett_Wireshark.pcapng differ
diff --git a/projects/Assignments/homework3/Tackett_dispackets.disbin b/projects/Assignments/homework3/Tackett_dispackets.disbin
new file mode 100644
index 0000000000000000000000000000000000000000..97e028dbc8fc06aed0c49550ca39908bbf202d0e
Binary files /dev/null and b/projects/Assignments/homework3/Tackett_dispackets.disbin differ
diff --git a/projects/Assignments/homework3/Tackett_dispackets.disbin.disbinidx b/projects/Assignments/homework3/Tackett_dispackets.disbin.disbinidx
new file mode 100644
index 0000000000000000000000000000000000000000..2e233e8f442f5a5453dc49b6ef83c3dc72deead9
Binary files /dev/null and b/projects/Assignments/homework3/Tackett_dispackets.disbin.disbinidx differ
diff --git a/projects/Assignments/nbproject/build-impl.xml b/projects/Assignments/nbproject/build-impl.xml
index 6072af6763d68a47105c0c0fdef3c488c699ec42..98d9dffdf429625ed651b3d1f9aceb2ac459ea6d 100644
--- a/projects/Assignments/nbproject/build-impl.xml
+++ b/projects/Assignments/nbproject/build-impl.xml
@@ -125,6 +125,7 @@ is divided into following sections:
         </condition>
         <condition property="have.sources">
             <or>
+                <available file="${src.FinalProjects.dir}"/>
                 <available file="${src.homework3.dir}"/>
                 <available file="${src.homework1.dir}"/>
                 <available file="${src.homework2.dir}"/>
@@ -230,6 +231,7 @@ is divided into following sections:
         <!-- You can override this target in the ../build.xml file. -->
     </target>
     <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
+        <fail unless="src.FinalProjects.dir">Must set src.FinalProjects.dir</fail>
         <fail unless="src.homework3.dir">Must set src.homework3.dir</fail>
         <fail unless="src.homework1.dir">Must set src.homework1.dir</fail>
         <fail unless="src.homework2.dir">Must set src.homework2.dir</fail>
@@ -253,7 +255,7 @@ is divided into following sections:
     </target>
     <target depends="-init-ap-cmdline-properties" if="ap.supported.internal" name="-init-macrodef-javac-with-processors">
         <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${src.homework3.dir}:${src.homework1.dir}:${src.homework2.dir}" name="srcdir"/>
+            <attribute default="${src.FinalProjects.dir}:${src.homework3.dir}:${src.homework1.dir}:${src.homework2.dir}" name="srcdir"/>
             <attribute default="${build.classes.dir}" name="destdir"/>
             <attribute default="${javac.classpath}" name="classpath"/>
             <attribute default="${javac.processorpath}" name="processorpath"/>
@@ -294,7 +296,7 @@ is divided into following sections:
     </target>
     <target depends="-init-ap-cmdline-properties" name="-init-macrodef-javac-without-processors" unless="ap.supported.internal">
         <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${src.homework3.dir}:${src.homework1.dir}:${src.homework2.dir}" name="srcdir"/>
+            <attribute default="${src.FinalProjects.dir}:${src.homework3.dir}:${src.homework1.dir}:${src.homework2.dir}" name="srcdir"/>
             <attribute default="${build.classes.dir}" name="destdir"/>
             <attribute default="${javac.classpath}" name="classpath"/>
             <attribute default="${javac.processorpath}" name="processorpath"/>
@@ -327,7 +329,7 @@ is divided into following sections:
     </target>
     <target depends="-init-macrodef-javac-with-processors,-init-macrodef-javac-without-processors" name="-init-macrodef-javac">
         <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${src.homework3.dir}:${src.homework1.dir}:${src.homework2.dir}" name="srcdir"/>
+            <attribute default="${src.FinalProjects.dir}:${src.homework3.dir}:${src.homework1.dir}:${src.homework2.dir}" name="srcdir"/>
             <attribute default="${build.classes.dir}" name="destdir"/>
             <attribute default="${javac.classpath}" name="classpath"/>
             <sequential>
@@ -915,11 +917,12 @@ is divided into following sections:
                 <include name="*"/>
             </dirset>
         </pathconvert>
-        <j2seproject3:depend srcdir="${src.homework3.dir}:${src.homework1.dir}:${src.homework2.dir}:${build.generated.subdirs}"/>
+        <j2seproject3:depend srcdir="${src.FinalProjects.dir}:${src.homework3.dir}:${src.homework1.dir}:${src.homework2.dir}:${build.generated.subdirs}"/>
     </target>
     <target depends="init,deps-jar,-pre-pre-compile,-pre-compile, -copy-persistence-xml,-compile-depend" if="have.sources" name="-do-compile">
         <j2seproject3:javac gensrcdir="${build.generated.sources.dir}"/>
         <copy todir="${build.classes.dir}">
+            <fileset dir="${src.FinalProjects.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.homework3.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.homework1.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
             <fileset dir="${src.homework2.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
@@ -943,7 +946,7 @@ is divided into following sections:
     <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
         <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
         <j2seproject3:force-recompile/>
-        <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.homework3.dir}:${src.homework1.dir}:${src.homework2.dir}"/>
+        <j2seproject3:javac excludes="" gensrcdir="${build.generated.sources.dir}" includes="${javac.includes}" sourcepath="${src.FinalProjects.dir}:${src.homework3.dir}:${src.homework1.dir}:${src.homework2.dir}"/>
     </target>
     <target name="-post-compile-single">
         <!-- Empty placeholder for easier customization. -->
@@ -1209,6 +1212,9 @@ is divided into following sections:
             <classpath>
                 <path path="${javac.classpath}"/>
             </classpath>
+            <fileset dir="${src.FinalProjects.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
+                <filename name="**/*.java"/>
+            </fileset>
             <fileset dir="${src.homework3.dir}" excludes="${bug5101868workaround},${excludes}" includes="${includes}">
                 <filename name="**/*.java"/>
             </fileset>
@@ -1225,6 +1231,9 @@ is divided into following sections:
             <arg line="${javadoc.endorsed.classpath.cmd.line.arg}"/>
         </javadoc>
         <copy todir="${dist.javadoc.dir}">
+            <fileset dir="${src.FinalProjects.dir}" excludes="${excludes}" includes="${includes}">
+                <filename name="**/doc-files/**"/>
+            </fileset>
             <fileset dir="${src.homework3.dir}" excludes="${excludes}" includes="${includes}">
                 <filename name="**/doc-files/**"/>
             </fileset>
diff --git a/projects/Assignments/nbproject/genfiles.properties b/projects/Assignments/nbproject/genfiles.properties
index a7551219a8e9d0c11a7420914e37e8d1a7c24ac8..389f40c35d09b10c547e5f59cc1c08f35ba603ed 100644
--- a/projects/Assignments/nbproject/genfiles.properties
+++ b/projects/Assignments/nbproject/genfiles.properties
@@ -1,8 +1,8 @@
-build.xml.data.CRC32=b21d1ee7
+build.xml.data.CRC32=80187eb2
 build.xml.script.CRC32=71581cc3
 build.xml.stylesheet.CRC32=8064a381@1.80.1.48
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=b21d1ee7
-nbproject/build-impl.xml.script.CRC32=3800b3a5
+nbproject/build-impl.xml.data.CRC32=80187eb2
+nbproject/build-impl.xml.script.CRC32=53c6ba36
 nbproject/build-impl.xml.stylesheet.CRC32=830a3534@1.80.1.48
diff --git a/projects/Assignments/nbproject/project.properties b/projects/Assignments/nbproject/project.properties
index dfc77e1dfa6738b878ec9d091d8ba3d02fc8db0d..773370d3fc0fa0b635eb9eedd5281b9c0023bede 100644
--- a/projects/Assignments/nbproject/project.properties
+++ b/projects/Assignments/nbproject/project.properties
@@ -76,6 +76,7 @@ run.test.classpath=\
     ${javac.test.classpath}:\
     ${build.test.classes.dir}
 source.encoding=UTF-8
+src.FinalProjects.dir=FinalProjects
 src.homework1.dir=homework1
 src.homework2.dir=homework2
 src.homework3.dir=homework3
diff --git a/projects/Assignments/nbproject/project.xml b/projects/Assignments/nbproject/project.xml
index 7fea14ab803a181d74afd843122afaf65df829fd..667d58689263f6d49e6a665ec562cb3c9c671879 100644
--- a/projects/Assignments/nbproject/project.xml
+++ b/projects/Assignments/nbproject/project.xml
@@ -5,6 +5,7 @@
         <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
             <name>Assignments: MV3500 Homework</name>
             <source-roots>
+                <root id="src.FinalProjects.dir"/>
                 <root id="src.homework3.dir"/>
                 <root id="src.homework1.dir"/>
                 <root id="src.homework2.dir"/>
diff --git a/projects/TcpExample3/Client/TcpClient/nbproject/private/private.properties b/projects/TcpExample3/Client/TcpClient/nbproject/private/private.properties
index c260af6fbd922e60da4bc9ff94bf53027d4fa593..196bc8698cb198083baa0aaa1d57e9fb90c20b42 100644
--- a/projects/TcpExample3/Client/TcpClient/nbproject/private/private.properties
+++ b/projects/TcpExample3/Client/TcpClient/nbproject/private/private.properties
@@ -1,2 +1,2 @@
 compile.on.save=true
-user.properties.file=C:\\Users\\don\\AppData\\Roaming\\NetBeans\\8.2\\build.properties
+user.properties.file=C:\\Users\\Justin Snell\\AppData\\Roaming\\NetBeans\\8.2\\build.properties
diff --git a/projects/TcpExample3/Server/TcpServer/nbproject/private/private.properties b/projects/TcpExample3/Server/TcpServer/nbproject/private/private.properties
index c260af6fbd922e60da4bc9ff94bf53027d4fa593..196bc8698cb198083baa0aaa1d57e9fb90c20b42 100644
--- a/projects/TcpExample3/Server/TcpServer/nbproject/private/private.properties
+++ b/projects/TcpExample3/Server/TcpServer/nbproject/private/private.properties
@@ -1,2 +1,2 @@
 compile.on.save=true
-user.properties.file=C:\\Users\\don\\AppData\\Roaming\\NetBeans\\8.2\\build.properties
+user.properties.file=C:\\Users\\Justin Snell\\AppData\\Roaming\\NetBeans\\8.2\\build.properties
diff --git a/projects/TcpExample4/TcpClient/TcpClient/nbproject/private/private.properties b/projects/TcpExample4/TcpClient/TcpClient/nbproject/private/private.properties
index c260af6fbd922e60da4bc9ff94bf53027d4fa593..196bc8698cb198083baa0aaa1d57e9fb90c20b42 100644
--- a/projects/TcpExample4/TcpClient/TcpClient/nbproject/private/private.properties
+++ b/projects/TcpExample4/TcpClient/TcpClient/nbproject/private/private.properties
@@ -1,2 +1,2 @@
 compile.on.save=true
-user.properties.file=C:\\Users\\don\\AppData\\Roaming\\NetBeans\\8.2\\build.properties
+user.properties.file=C:\\Users\\Justin Snell\\AppData\\Roaming\\NetBeans\\8.2\\build.properties