Skip to content
Snippets Groups Projects
Commit 768097d5 authored by runem's avatar runem
Browse files

Merge origin/master

parents f2227fbb 46c4b578
No related branches found
No related tags found
No related merge requests found
Showing
with 421 additions and 847 deletions
Simple client/server connection. Run the server first, then client.
You will see when the server begins running the output will show "FisherServer has started..."
Once the clent begins running you should see "FisherClient creating socket..." in the output.
The client/server connection will then run 10 loops of the server asking "Why did the chicken cross the road?"
And the client will reply "To get to the other side" along with a loop count. After 10 reps the
client will exit and the server will close.
package MV3500Cohort2021JulySeptember.homework3.Fisher;
/**
* Copyright (c) 2008-2021, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved.
* This work is provided under a BSD open-source license, see project license.html and license.txt
* @author adfis
*
* This simulation has two entities moving towards each other and when they
* collide a detonation happens.
*/
import edu.nps.moves.dis7.enumerations.ForceID;
import edu.nps.moves.dis7.enumerations.VariableRecordType;
import edu.nps.moves.dis7.pdus.CommentPdu;
import edu.nps.moves.dis7.pdus.EntityID;
import edu.nps.moves.dis7.pdus.EntityStatePdu;
import edu.nps.moves.dis7.pdus.FirePdu;
import edu.nps.moves.dis7.pdus.DetonationPdu;
import edu.nps.moves.dis7.pdus.MunitionDescriptor;
import edu.nps.moves.dis7.pdus.Pdu;
import edu.nps.moves.dis7.pdus.Vector3Float;
import edu.nps.moves.dis7.utilities.DisThreadedNetworkInterface;
import edu.nps.moves.dis7.utilities.PduFactory;
import edu.nps.moves.dis7.utilities.stream.PduRecorder;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
/** The purpose of this program is to provide an easily modifiable example simulation program
* that includes DIS-capable entities doing tasks and reporting them to the network.
* Default settings include PDU recording turned on by default.
*
*/
public class ExampleSimulationProgramFisher
{
private boolean verboseComments = true;
static final String NETWORK_ADDRESS_DEFAULT = "239.1.2.3";
static final int NETWORK_PORT_DEFAULT = 3000;
static String networkAddress = NETWORK_ADDRESS_DEFAULT;
static int networkPort = NETWORK_PORT_DEFAULT;
String DEFAULT_OUTPUT_DIRECTORY = "./pduLog";
/**
* This runSimulation() method is for you, a
* programmer-modifiable method for defining and running a new simulation of interest.
* Welcome! Other parts of this program handle bookkeeping and plumbing tasks so that
* you can focus on your model entities and activities.
* Expandable support includes DIS EntityStatePdu, FirePdu and CommentPdu all available for
* modification and sending in a simulation loop.
* Continuous improvement efforts seek to make this program as easy and straightforward
* as possible for DIS simulationists to use and adapt.
* All of the other methods are setup, teardown and configuration that you may find
* interesting, even helpful, but don't really have to worry about.
*/
@SuppressWarnings("SleepWhileInLoop") // yes we do that
public void runSimulation ()
{
try
{
/** seconds for real-time execution (not simulation time, which may or may not be the same) */
final double SIMULATION_LOOP_DURATION_SECONDS = 1.0;
final int SIMULATION_MAX_LOOP_COUNT = 10; // be deliberate out out there! also avoid infinite loops.
int simulationLoopCount = 0; // variable, initialized at 0
boolean simulationComplete = false; // sentinel variable as termination condition,, are we done yet?
// TODO reset clock to zero each time for consistent outputs
// Your model setup: define participants. who's who in this zoo?
// Assuming you keep track of entity objects... here is some support for for Entity 1.
// create PDU objects and set their values.
EntityID entityID_1 = new EntityID();
entityID_1.setSiteID(1).setApplicationID(2).setEntityID(3); // made-up example ID;
// TODO someday, use enumerations; is there a unique site triplet for MOVES Institute?
EntityID entityID_2 = new EntityID();
entityID_2.setSiteID(4).setApplicationID(5).setEntityID(6);
EntityStatePdu entityStatePdu_1 = pduFactory.makeEntityStatePdu();
entityStatePdu_1.setEntityID(entityID_1);
entityStatePdu_1.setForceId(ForceID.FRIENDLY);
EntityStatePdu entityStatePdu_2 = pduFactory.makeEntityStatePdu();
entityStatePdu_2.setEntityID(entityID_2);
entityStatePdu_2.getEntityLocation().setX(10);
entityStatePdu_2.setForceId(ForceID.OPPOSING);
FirePdu firePdu_1a = pduFactory.makeFirePdu(); // for entity 1 first weapon (if any)
FirePdu firePdu_1b = pduFactory.makeFirePdu(); // for entity 1 second weapon (if any)
// should we customize this munition? what is it for your simulation?
firePdu_1a.setRange(1500.0f);
Vector3Float pVelocity = new Vector3Float();
pVelocity.setX(1.0f);
pVelocity.setY(5.0f);
pVelocity.setZ(0.0f);
firePdu_1a.setVelocity(pVelocity);
// TODO simulation management PDUs for startup, planning to design special class support
MunitionDescriptor pDescriotor = new MunitionDescriptor();
pDescriotor.setQuantity(10).setRate(30);
DetonationPdu detonationPdu = pduFactory.makeDetonationPdu();
detonationPdu.setDescriptor(pDescriotor);
// loop the simulation while allowed, programmer can set additional conditions to break out and finish
while (simulationLoopCount < SIMULATION_MAX_LOOP_COUNT) // are we done yet?
{
simulationLoopCount++; // good practice: increment loop counter as first action in that loop
// =============================================================================================
// * your own simulation code starts here! *
// =============================================================================================
// are there any other variables to modify at the beginning of your loop?
// compute a track, update an ESPDU, whatever it is that your model is doing...
// Where is my entity? Insert changes in position; this sample only changes X position.
entityStatePdu_1.getEntityLocation().setX(entityStatePdu_1.getEntityLocation().getX() + 1.0); // 1m per timestep
entityStatePdu_2.getEntityLocation().setX(entityStatePdu_2.getEntityLocation().getX() - 1.0);
// decide whether to fire, and then update the firePdu. Hmmm, you might want a target to shoort at!
// etc. etc. your code goes here for your simulation of interest
// something happens between my simulation entities, la de da de da...
System.out.println ("... My simulation just did something, no really...");
// make your reports: narrative code for CommentPdu here (set all to empty strings to avoid sending)
narrativeMessage1 = "MV3500 ExampleSimulationProgramFisher";
narrativeMessage2 = "runSimulation() loop " + simulationLoopCount;
narrativeMessage3 = "this is working!"; // intentionally blank for testing
// your loop termination condition goes here
if (simulationLoopCount > 4) // for example
{
simulationComplete = true;
}
// =============================================================================================
// * your own simulation code is finished here! *
// =============================================================================================
// staying synchronized with timestep: wait duration for elapsed time in this loop
// Thread.sleep needs a (long) parameter for milliseconds, which are clumsy to use sometimes
Thread.sleep((long)(SIMULATION_LOOP_DURATION_SECONDS * 1000)); // seconds * (1000 msec/sec) = milliseconds
System.out.println ("... [Pausing for " + SIMULATION_LOOP_DURATION_SECONDS + " seconds]");
// OK now send the status PDUs for this loop, and then continue
System.out.println ("sending PDUs for simulation step " + simulationLoopCount + ", monitor loopback to confirm sent");
// Below is the PDU that comes out as "Comment" in the info
// sendAllPdusForLoopTimestep(entityStatePdu_1, entityStatePdu_2, firePdu_1a, timeStepComment, narrativeMessage1, narrativeMessage2, narrativeMessage3);
System.out.println ("... [PDUs successfully sent for this loop]");
// ===============================
// loop now finished, check whether to terminate if simulation complete, otherwise continue
if (simulationComplete || (simulationLoopCount > 10000)) // for example; including fail-safe condition is good
{
sendSinglePdu(detonationPdu);
System.out.println ("... [Termination condition met, simulationComplete=" + simulationComplete + "]"); // ", final loopCount=" + loopCount +
break;
}
} // end of simulation loop
// This is the FINAL message that will be sent when the loop is done
narrativeMessage2 = "We have completed to simulation successfully"; // all done
sendCommentPdu(narrativeComment, narrativeMessage1, narrativeMessage2);
System.out.println ("... [final CommentPdu successfully sent for simulation]");
// TODO simulation management PDUs
}
catch (InterruptedException iex) // handle any exception that your code might choose to provoke!
{
Logger.getLogger(ExampleSimulationProgramFisher.class.getName()).log(Level.SEVERE, null, iex);
}
}
/* **************************** infrastructure code, modification is seldom needed ************************* */
//private boolean verboseComments = true;
String narrativeMessage1 = new String();
String narrativeMessage2 = new String();
String narrativeMessage3 = new String();
/* VariableRecordType enumerations have potential use with CommentPdu logs */
/* TODO contrast to EntityType */
VariableRecordType descriptionComment = VariableRecordType.DESCRIPTION;
VariableRecordType narrativeComment = VariableRecordType.COMPLETE_EVENT_REPORT;
VariableRecordType statusComment = VariableRecordType.APPLICATION_STATUS;
VariableRecordType timeStepComment = VariableRecordType.APPLICATION_TIMESTEP;
VariableRecordType otherComment = VariableRecordType.OTHER;
/**
* Output prefix to identify this class, helps with logging
*/
private final static String TRACE_PREFIX = "[" + ExampleSimulationProgramFisher.class.getName() + "] ";
// class variables
PduFactory pduFactory = new PduFactory();
DisThreadedNetworkInterface disNetworkInterface;
DisThreadedNetworkInterface.PduListener pduListener;
Pdu receivedPdu;
//static final String NETWORK_ADDRESS_DEFAULT = "239.1.2.3";
//static final int NETWORK_PORT_DEFAULT = 3000;
//static String networkAddress = NETWORK_ADDRESS_DEFAULT;
//static int networkPort = NETWORK_PORT_DEFAULT;
// String DEFAULT_OUTPUT_DIRECTORY = "./pduLog";
/**
* Constructor design goal: additional built-in initialization conveniences can go here
* to keep student efforts focused on the runSimulation() method.
*/
public ExampleSimulationProgramFisher()
{
// Constructor is under consideration. Constructor is not currently needed.
}
/**
* Utility Constructor that allows your example simulation program to override default network address and port
* @param address network address to use
* @param port corresponding network port to use
*/
public ExampleSimulationProgramFisher(String address, int port)
{
setNetworkAddress(address);
setNetworkPort(port);
}
/**
* @return the networkAddress
*/
public String getNetworkAddress()
{
return networkAddress;
}
/**
* @param newNetworkAddress the networkAddress to set
*/
public final void setNetworkAddress(String newNetworkAddress)
{
ExampleSimulationProgramFisher.networkAddress = newNetworkAddress;
}
/**
* @return the networkPort
*/
public int getNetworkPort()
{
return networkPort;
}
/**
* @param newNetworkPort the networkPort to set
*/
public final void setNetworkPort(int newNetworkPort)
{
ExampleSimulationProgramFisher.networkPort = newNetworkPort;
}
/**
* Initialize network interface, choosing best available network interface
*/
public void setUpNetworkInterface()
{
disNetworkInterface = new DisThreadedNetworkInterface(getNetworkAddress(), getNetworkPort());
System.out.println("Network confirmation:" +
" address=" + disNetworkInterface.getAddress() + // disNetworkInterface.getMulticastGroup() +
" port=" + disNetworkInterface.getPort()); // + disNetworkInterface.getDisPort());
pduListener = new DisThreadedNetworkInterface.PduListener()
{
/** Callback handler for listener */
@Override
public void incomingPdu(Pdu newPdu)
{
receivedPdu = newPdu;
}
};
disNetworkInterface.addListener(pduListener);
}
/** All done, release network resources */
public void tearDownNetworkInterface()
{
disNetworkInterface.removeListener(pduListener);
disNetworkInterface.close();
// disNetworkInterface.kill(); // renamed as close(), deprecated
// disNetworkInterface = null; // making sure no possibility of zombie process remaining...
}
/**
* Send a single Protocol Data Unit (PDU) of any type
* @param pdu the pdu to send
*/
private void sendSinglePdu(Pdu pdu)
{
try
{
disNetworkInterface.send(pdu);
Thread.sleep(100); // TODO consider refactoring the wait logic and moving externally
}
catch (InterruptedException ex)
{
System.err.println(this.getClass().getName() + " Error sending PDU: " + ex.getLocalizedMessage());
System.exit(1);
}
}
/**
* Send Comment PDU
* @see <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html">Passing Information to a Method or a Constructor</a> Arbitrary Number of Arguments
* @param commentType enumeration value describing purpose of the narrative comment
* @param comments String array of narrative comments
*/
public void sendCommentPdu(VariableRecordType commentType,
// vararg... variable-length set of String comments can optionally follow
String... comments)
{
// sendAllPdusForLoopTimestep (null, null, null, commentType, comments);
}
/**
* Send EntityState, Fire, Comment PDUs that got updated for this loop, reflecting state of current simulation timestep.
* @see <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html">Passing Information to a Method or a Constructor</a> Arbitrary Number of Arguments
* @param entityStatePdu1 the ESPDU to send, if any
* @param entityStatePdu2 the ESPDU to send, if any
* @param firePdu the FirePDU to send, if any
* @param detonationPdu the det to send
* @param commentType enumeration value describing purpose of the narrative comment
* @param comments String array of narrative comments
*/
public void sendAllPdusForLoopTimestep(EntityStatePdu entityStatePdu1,
EntityStatePdu entityStatePdu2,
FirePdu firePdu,
DetonationPdu detonationPdu,
VariableRecordType commentType,
// vararg... variable-length set of String comments can optionally follow
String... comments)
{
if (entityStatePdu1 != null)
sendSinglePdu(entityStatePdu1);
if (entityStatePdu2 != null)
sendSinglePdu(entityStatePdu2);
if (firePdu != null)
sendSinglePdu(firePdu); // bang
//if (detonationPdu != null)
// sendSinglePdu(detonationPdu);
//
if ((comments != null) && (comments.length > 0))
{
ArrayList<String> newCommentsList = new ArrayList<>();
for (String comment : comments)
{
if (!comment.isEmpty())
{
newCommentsList.add(comment); // OK found something to send
}
}
if (!newCommentsList.isEmpty())
{
if (commentType == null)
commentType = otherComment; // fallback value otherComment
// now build the commentPdu from these string inputs, thus constructing a narrative entry
CommentPdu commentPdu = pduFactory.makeCommentPdu(commentType, newCommentsList.toArray(new String[0])); // comments);
sendSinglePdu(commentPdu);
if (isVerboseComments())
System.out.println("*** [Narrative comment sent: " + commentType.name() + "] " + newCommentsList.toString());
}
}
}
/**
* Main method is first executed when a program instance is loaded.
* @see <a href="https://docs.oracle.com/javase/tutorial/getStarted/application/index.html">Java Tutorials: A Closer Look at the "Hello World!" Application</a>
* @param args command-line arguments are an array of optional String parameters that are passed from execution environment during invocation
*/
public static void main(String[] args)
{
System.out.println(TRACE_PREFIX + "started...");
ExampleSimulationProgramFisher thisProgram = new ExampleSimulationProgramFisher(); // creates instance
// initial execution: can handle args array of initialization arguments here
if (args.length == 2)
{
if ((args[0] != null) && !args[0].isEmpty())
thisProgram.setNetworkAddress(args[0]);
if ((args[1] != null) && !args[1].isEmpty())
thisProgram.setNetworkPort(Integer.parseInt(args[1]));
}
else if (args.length != 0)
{
System.err.println("Usage: " + thisProgram.getClass().getName() + " [address port]");
System.exit(-1);
}
// OK here we go...
thisProgram.setUpNetworkInterface();
String DEFAULT_OUTPUT_DIRECTORY = "./pduLog";
String outputDirectory = DEFAULT_OUTPUT_DIRECTORY;
System.out.println("Beginning pdu save to directory " + outputDirectory);
PduRecorder pduRecorder = new PduRecorder(outputDirectory, networkAddress, networkPort); // assumes save
//
thisProgram.runSimulation (); // ... your simulation execution code goes in there ...
pduRecorder.stop();
thisProgram.tearDownNetworkInterface(); // make sure no processes are left lingering
System.out.println(TRACE_PREFIX + "complete."); // report successful completion
}
/**
* @return whether verboseComments mode is enabled
*/
public boolean isVerboseComments() {
return verboseComments;
}
/**
* @param newVerboseComments whether verboseComments mode is enabled
*/
public void setVerboseComments(boolean newVerboseComments) {
this.verboseComments = newVerboseComments;
}
}
/**
* Copyright (c) 2008-2021, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved.
* This work is provided under a BSD open-source license, see project license.html and license.txt
*
* This Program is a modified version of ExampleSimulationProgramFisher in order to see the
* verbose plain text pdu log. I was unable to figure out the issue in my original code,
* so I just copied the example and pasted my additions into this file.
*
* @author adfis
*/
package MV3500Cohort2021JulySeptember.homework3.Fisher;
import edu.nps.moves.dis7.enumerations.*; // match any
import edu.nps.moves.dis7.pdus.*; // match any of the PDU classes, easier than listing individually
import edu.nps.moves.dis7.utilities.DisThreadedNetworkInterface;
import edu.nps.moves.dis7.utilities.PduFactory;
import edu.nps.moves.dis7.utilities.stream.PduRecorder;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
/** The purpose of this program is to provide an easily modifiable example simulation program
* that includes DIS-capable entities doing tasks and reporting them to the network.
* Default settings include PDU recording turned on by default.
*/
public class ExampleSimulationProgramFisher_2
{
private boolean verboseComments = true;
static final String NETWORK_ADDRESS_DEFAULT = "239.1.2.3";
static final int NETWORK_PORT_DEFAULT = 3000;
static String networkAddress = NETWORK_ADDRESS_DEFAULT;
static int networkPort = NETWORK_PORT_DEFAULT;
String DEFAULT_OUTPUT_DIRECTORY = "./pduLog";
/**
* This runSimulationLoops() method is for you, a
* programmer-modifiable method for defining and running a new simulation of interest.
* Welcome! Other parts of this program handle bookkeeping and plumbing tasks so that
* you can focus on your model entities and activities.
* Expandable support includes DIS EntityStatePdu, FirePdu and CommentPdu all available for
* modification and sending in a simulation loop.
* Continuous improvement efforts seek to make this program as easy and straightforward
* as possible for DIS simulationists to use and adapt.
* All of the other methods are setup, teardown and configuration that you may find
* interesting, even helpful, but don't really have to worry about.
*/
@SuppressWarnings("SleepWhileInLoop") // yes we do that
public void runSimulationLoops ()
{
try
{
/** seconds for real-time execution (not simulation time, which may or may not be the same) */
final double SIMULATION_LOOP_DURATION_SECONDS = 1.0;
final int SIMULATION_MAX_LOOP_COUNT = 10; // be deliberate out out there! also avoid infinite loops.
int simulationLoopCount = 0; // variable, initialized at 0
boolean simulationComplete = false; // sentinel variable as termination condition,, are we done yet?
// TODO reset clock to zero each time for consistent outputs
// Your model setup: define participants. who's who in this zoo?
// Assuming you keep track of entity objects... here is some support for for Entity 1.
// create PDU objects and set their values.
EntityID entityID_1 = new EntityID();
entityID_1.setSiteID(1).setApplicationID(2).setEntityID(3); // made-up example ID;
// create PDU objects and set their values.
EntityID entityID_2 = new EntityID();
entityID_2.setSiteID(4).setApplicationID(5).setEntityID(6);
// TODO someday, use enumerations; is there a unique site triplet for MOVES Institute?
EntityStatePdu entityStatePdu_1 = pduFactory.makeEntityStatePdu();
entityStatePdu_1.setEntityID(entityID_1);
entityStatePdu_1.setForceId(ForceID.FRIENDLY);
EntityStatePdu entityStatePdu_2 = pduFactory.makeEntityStatePdu();
entityStatePdu_2.setEntityID(entityID_2);
entityStatePdu_2.getEntityLocation().setX(10);
entityStatePdu_2.setForceId(ForceID.OPPOSING);
FirePdu firePdu_1a = pduFactory.makeFirePdu(); // for entity 1 first weapon (if any)
FirePdu firePdu_1b = pduFactory.makeFirePdu(); // for entity 1 second weapon (if any)
// should we customize this munition? what is it for your simulation?
firePdu_1a.setRange(1500.0f);
Vector3Float pVelocity = new Vector3Float();
pVelocity.setX(1.0f);
pVelocity.setY(5.0f);
pVelocity.setZ(0.0f);
firePdu_1a.setVelocity(pVelocity);
// TODO simulation management PDUs for startup, planning to design special class support
MunitionDescriptor pDescriotor = new MunitionDescriptor();
pDescriotor.setQuantity(10).setRate(30);
DetonationPdu detonationPdu = pduFactory.makeDetonationPdu();
detonationPdu.setDescriptor(pDescriotor);
// loop the simulation while allowed, programmer can set additional conditions to break out and finish
while (simulationLoopCount < SIMULATION_MAX_LOOP_COUNT) // are we done yet?
{
simulationLoopCount++; // good practice: increment loop counter as first action in that loop
// =============================================================================================
// * your own simulation code starts here! *
// =============================================================================================
// are there any other variables to modify at the beginning of your loop?
// compute a track, update an ESPDU, whatever it is that your model is doing...
// Where is my entity? Insert changes in position; this sample only changes X position.
entityStatePdu_1.getEntityLocation().setX(entityStatePdu_1.getEntityLocation().getX() + 1.0); // 1m per timestep
entityStatePdu_2.getEntityLocation().setX(entityStatePdu_2.getEntityLocation().getX() - 1.0);
// decide whether to fire, and then update the firePdu. Hmmm, you might want a target to shoort at!
// etc. etc. your code goes here for your simulation of interest
// something happens between my simulation entities, la de da de da...
System.out.println ("... My simulation just did something, no really...");
// make your reports: narrative code for CommentPdu here (set all to empty strings to avoid sending)
narrativeMessage1 = "MV3500 ExampleSimulationProgramFisher_2";
narrativeMessage2 = "runSimulation() loop " + simulationLoopCount;
narrativeMessage3 = "this is working!"; // intentionally blank for testing
// your loop termination condition goes here
if (simulationLoopCount > 4) // for example
{
simulationComplete = true;
}
// =============================================================================================
// * your own simulation code is finished here! *
// =============================================================================================
// staying synchronized with timestep: wait duration for elapsed time in this loop
// Thread.sleep needs a (long) parameter for milliseconds, which are clumsy to use sometimes
Thread.sleep((long)(SIMULATION_LOOP_DURATION_SECONDS * 1000)); // seconds * (1000 msec/sec) = milliseconds
System.out.println ("... [Pausing for " + SIMULATION_LOOP_DURATION_SECONDS + " seconds]");
// OK now send the status PDUs for this loop, and then continue
System.out.println ("sending PDUs for simulation step " + simulationLoopCount + ", monitor loopback to confirm sent");
sendAllPdusForLoopTimestep(entityStatePdu_1, firePdu_1a, timeStepComment, narrativeMessage1, narrativeMessage2, narrativeMessage3);
sendSinglePdu(entityStatePdu_2); // me too i.e. 2!
System.out.println ("... [PDUs successfully sent for this loop]");
// ===============================
// loop now finished, check whether to terminate if simulation complete, otherwise continue
if (simulationComplete || (simulationLoopCount > 10000)) // for example; including fail-safe condition is good
{
sendSinglePdu(detonationPdu);
System.out.println ("... [Termination condition met, simulationComplete=" + simulationComplete + "]"); // ", final loopCount=" + loopCount +
break;
}
} // end of simulation loop
narrativeMessage2 = "runSimulation() completed successfully"; // all done
sendCommentPdu(narrativeComment, narrativeMessage1, narrativeMessage2, narrativeMessage3);
System.out.println ("... [final CommentPdu successfully sent for simulation]");
// TODO simulation management PDUs
}
catch (InterruptedException iex) // handle any exception that your code might choose to provoke!
{
Logger.getLogger(ExampleSimulationProgramFisher_2.class.getName()).log(Level.SEVERE, null, iex);
}
}
/* **************************** infrastructure code, modification is seldom needed ************************* */
String narrativeMessage1 = new String();
String narrativeMessage2 = new String();
String narrativeMessage3 = new String();
/* VariableRecordType enumerations have potential use with CommentPdu logs */
/* TODO contrast to EntityType */
VariableRecordType descriptionComment = VariableRecordType.DESCRIPTION;
VariableRecordType narrativeComment = VariableRecordType.COMPLETE_EVENT_REPORT;
VariableRecordType statusComment = VariableRecordType.APPLICATION_STATUS;
VariableRecordType timeStepComment = VariableRecordType.APPLICATION_TIMESTEP;
VariableRecordType otherComment = VariableRecordType.OTHER;
/**
* Output prefix to identify this class, helps with logging
*/
private final static String TRACE_PREFIX = "[" + ExampleSimulationProgramFisher_2.class.getName() + "] ";
// class variables
PduFactory pduFactory = new PduFactory();
DisThreadedNetworkInterface disNetworkInterface;
DisThreadedNetworkInterface.PduListener pduListener;
Pdu receivedPdu;
PduRecorder pduRecorder;
/**
* Constructor design goal: additional built-in initialization conveniences can go here
* to keep student efforts focused on the runSimulation() method.
*/
public ExampleSimulationProgramFisher_2()
{
// Constructor is under consideration. Constructor is not currently needed.
}
/**
* Utility Constructor that allows your example simulation program to override default network address and port
* @param address network address to use
* @param port corresponding network port to use
*/
public ExampleSimulationProgramFisher_2(String address, int port)
{
setNetworkAddress(address);
setNetworkPort(port);
}
/**
* @return the networkAddress
*/
public String getNetworkAddress()
{
return networkAddress;
}
/**
* @param newNetworkAddress the networkAddress to set
*/
public final void setNetworkAddress(String newNetworkAddress)
{
ExampleSimulationProgramFisher_2.networkAddress = newNetworkAddress;
}
/**
* @return the networkPort
*/
public int getNetworkPort()
{
return networkPort;
}
/**
* @param newNetworkPort the networkPort to set
*/
public final void setNetworkPort(int newNetworkPort)
{
ExampleSimulationProgramFisher_2.networkPort = newNetworkPort;
}
/**
* Initialize network interface, choosing best available network interface
*/
public void setUpNetworkInterface()
{
disNetworkInterface = new DisThreadedNetworkInterface(getNetworkAddress(), getNetworkPort());
disNetworkInterface.setDescriptor ("ExampleSimulationProgramFisher_2 pdu looping");
System.out.println("Network confirmation:" +
" address=" + disNetworkInterface.getAddress() + // disNetworkInterface.getMulticastGroup() +
" port=" + disNetworkInterface.getPort()); // + disNetworkInterface.getDisPort());
pduListener = new DisThreadedNetworkInterface.PduListener()
{
/** Callback handler for listener */
@Override
public void incomingPdu(Pdu newPdu)
{
receivedPdu = newPdu;
}
};
disNetworkInterface.addListener(pduListener);
String outputDirectory = DEFAULT_OUTPUT_DIRECTORY;
System.out.println("Beginning pdu save to directory " + outputDirectory);
pduRecorder = new PduRecorder(outputDirectory, getNetworkAddress(), getNetworkPort()); // assumes save
pduRecorder.setDescriptor ("ExampleSimulationProgramFisher_2 pduRecorder");
pduRecorder.start(); // begin running
}
/** All done, release network resources */
public void tearDownNetworkInterface()
{
pduRecorder.stop();
disNetworkInterface.removeListener(pduListener);
disNetworkInterface.close();
// disNetworkInterface.kill(); // renamed as close(), deprecated
// disNetworkInterface = null; // making sure no possibility of zombie process remaining...
}
/**
* Send a single Protocol Data Unit (PDU) of any type
* @param pdu the pdu to send
*/
private void sendSinglePdu(Pdu pdu)
{
try
{
disNetworkInterface.send(pdu);
Thread.sleep(100); // TODO consider refactoring the wait logic and moving externally
}
catch (InterruptedException ex)
{
System.err.println(this.getClass().getName() + " Error sending PDU: " + ex.getLocalizedMessage());
System.exit(1);
}
}
/**
* Send Comment PDU
* @see <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html">Passing Information to a Method or a Constructor</a> Arbitrary Number of Arguments
* @param commentType enumeration value describing purpose of the narrative comment
* @param comments String array of narrative comments
*/
public void sendCommentPdu(VariableRecordType commentType,
// vararg... variable-length set of String comments can optionally follow
String... comments)
{
sendAllPdusForLoopTimestep (null, null, commentType, comments);
}
/**
* Send EntityState, Fire, Comment PDUs that got updated for this loop, reflecting state of current simulation timestep.
* @see <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html">Passing Information to a Method or a Constructor</a> Arbitrary Number of Arguments
* @param entityStatePdu the ESPDU to send, if any
* @param firePdu the FirePDU to send, if any
* @param commentType enumeration value describing purpose of the narrative comment
* @param comments String array of narrative comments
*/
public void sendAllPdusForLoopTimestep(EntityStatePdu entityStatePdu,
FirePdu firePdu,
VariableRecordType commentType,
// vararg... variable-length set of String comments can optionally follow
String... comments)
{
if (entityStatePdu != null)
sendSinglePdu(entityStatePdu);
if (firePdu != null)
sendSinglePdu(firePdu); // bang
if ((comments != null) && (comments.length > 0))
{
ArrayList<String> newCommentsList = new ArrayList<>();
for (String comment : comments)
{
if (!comment.isEmpty())
{
newCommentsList.add(comment); // OK found something to send
}
}
if (!newCommentsList.isEmpty())
{
if (commentType == null)
commentType = otherComment; // fallback value otherComment
// now build the commentPdu from these string inputs, thus constructing a narrative entry
CommentPdu commentPdu = pduFactory.makeCommentPdu(commentType, newCommentsList.toArray(new String[0])); // comments);
sendSinglePdu(commentPdu);
if (isVerboseComments())
System.out.println("*** [Narrative comment sent: " + commentType.name() + "] " + newCommentsList.toString());
}
}
}
/**
* Main method is first executed when a program instance is loaded.
* @see <a href="https://docs.oracle.com/javase/tutorial/getStarted/application/index.html">Java Tutorials: A Closer Look at the "Hello World!" Application</a>
* @param args command-line arguments are an array of optional String parameters that are passed from execution environment during invocation
*/
public static void main(String[] args)
{
System.out.println(TRACE_PREFIX + "started...");
ExampleSimulationProgramFisher_2 thisProgram = new ExampleSimulationProgramFisher_2(); // creates instance
// initial execution: can handle args array of initialization arguments here
if (args.length == 2)
{
if ((args[0] != null) && !args[0].isEmpty())
thisProgram.setNetworkAddress(args[0]);
if ((args[1] != null) && !args[1].isEmpty())
thisProgram.setNetworkPort(Integer.parseInt(args[1]));
}
else if (args.length != 0)
{
System.err.println("Usage: " + thisProgram.getClass().getName() + " [address port]");
System.exit(-1);
}
// OK here we go...
thisProgram.setUpNetworkInterface();
thisProgram.runSimulationLoops (); // ... your simulation execution code goes in there ...
thisProgram.tearDownNetworkInterface(); // make sure no processes are left lingering
System.out.println(TRACE_PREFIX + "complete."); // report successful completion
}
/**
* @return whether verboseComments mode is enabled
*/
public boolean isVerboseComments() {
return verboseComments;
}
/**
* @param newVerboseComments whether verboseComments mode is enabled
*/
public void setVerboseComments(boolean newVerboseComments) {
this.verboseComments = newVerboseComments;
}
}
/**
* Copyright (c) 2008-2021, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved.
* This work is provided under a BSD open-source license, see project license.html and license.txt
*
* This Program is a modified version of ExampleSimulationProgramFisher in order to see the
* verbose plain text pdu log. I was unable to figure out the issue in my original code,
* so I just copied the example and pasted my additions into this file.
*
* @author adfis
*/
package MV3500Cohort2021JulySeptember.homework3.Fisher;
import edu.nps.moves.dis7.enumerations.*; // match any
import edu.nps.moves.dis7.pdus.*; // match any of the PDU classes, easier than listing individually
import edu.nps.moves.dis7.utilities.DisThreadedNetworkInterface;
import edu.nps.moves.dis7.utilities.PduFactory;
import edu.nps.moves.dis7.utilities.stream.PduRecorder;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
/** The purpose of this program is to provide an easily modifiable example simulation program
* that includes DIS-capable entities doing tasks and reporting them to the network.
* Default settings include PDU recording turned on by default.
*/
public class ExampleSimulationProgramFisher_2
{
private boolean verboseComments = true;
static final String NETWORK_ADDRESS_DEFAULT = "239.1.2.3";
static final int NETWORK_PORT_DEFAULT = 3000;
static String networkAddress = NETWORK_ADDRESS_DEFAULT;
static int networkPort = NETWORK_PORT_DEFAULT;
String DEFAULT_OUTPUT_DIRECTORY = "./pduLog";
/**
* This runSimulationLoops() method is for you, a
* programmer-modifiable method for defining and running a new simulation of interest.
* Welcome! Other parts of this program handle bookkeeping and plumbing tasks so that
* you can focus on your model entities and activities.
* Expandable support includes DIS EntityStatePdu, FirePdu and CommentPdu all available for
* modification and sending in a simulation loop.
* Continuous improvement efforts seek to make this program as easy and straightforward
* as possible for DIS simulationists to use and adapt.
* All of the other methods are setup, teardown and configuration that you may find
* interesting, even helpful, but don't really have to worry about.
*/
@SuppressWarnings("SleepWhileInLoop") // yes we do that
public void runSimulationLoops ()
{
try
{
/** seconds for real-time execution (not simulation time, which may or may not be the same) */
final double SIMULATION_LOOP_DURATION_SECONDS = 1.0;
final int SIMULATION_MAX_LOOP_COUNT = 10; // be deliberate out out there! also avoid infinite loops.
int simulationLoopCount = 0; // variable, initialized at 0
boolean simulationComplete = false; // sentinel variable as termination condition,, are we done yet?
// TODO reset clock to zero each time for consistent outputs
// Your model setup: define participants. who's who in this zoo?
// Assuming you keep track of entity objects... here is some support for for Entity 1.
// create PDU objects and set their values.
EntityID entityID_1 = new EntityID();
entityID_1.setSiteID(1).setApplicationID(2).setEntityID(3); // made-up example ID;
// create PDU objects and set their values.
EntityID entityID_2 = new EntityID();
entityID_2.setSiteID(4).setApplicationID(5).setEntityID(6);
// TODO someday, use enumerations; is there a unique site triplet for MOVES Institute?
EntityStatePdu entityStatePdu_1 = pduFactory.makeEntityStatePdu();
entityStatePdu_1.setEntityID(entityID_1);
entityStatePdu_1.setForceId(ForceID.FRIENDLY);
EntityStatePdu entityStatePdu_2 = pduFactory.makeEntityStatePdu();
entityStatePdu_2.setEntityID(entityID_2);
entityStatePdu_2.getEntityLocation().setX(10);
entityStatePdu_2.setForceId(ForceID.OPPOSING);
FirePdu firePdu_1a = pduFactory.makeFirePdu(); // for entity 1 first weapon (if any)
FirePdu firePdu_1b = pduFactory.makeFirePdu(); // for entity 1 second weapon (if any)
// should we customize this munition? what is it for your simulation?
firePdu_1a.setRange(1500.0f);
Vector3Float pVelocity = new Vector3Float();
pVelocity.setX(1.0f);
pVelocity.setY(5.0f);
pVelocity.setZ(0.0f);
firePdu_1a.setVelocity(pVelocity);
// TODO simulation management PDUs for startup, planning to design special class support
MunitionDescriptor pDescriotor = new MunitionDescriptor();
pDescriotor.setQuantity(10).setRate(30);
DetonationPdu detonationPdu = pduFactory.makeDetonationPdu();
detonationPdu.setDescriptor(pDescriotor);
// loop the simulation while allowed, programmer can set additional conditions to break out and finish
while (simulationLoopCount < SIMULATION_MAX_LOOP_COUNT) // are we done yet?
{
simulationLoopCount++; // good practice: increment loop counter as first action in that loop
// =============================================================================================
// * your own simulation code starts here! *
// =============================================================================================
// are there any other variables to modify at the beginning of your loop?
// compute a track, update an ESPDU, whatever it is that your model is doing...
// Where is my entity? Insert changes in position; this sample only changes X position.
entityStatePdu_1.getEntityLocation().setX(entityStatePdu_1.getEntityLocation().getX() + 1.0); // 1m per timestep
entityStatePdu_2.getEntityLocation().setX(entityStatePdu_2.getEntityLocation().getX() - 1.0);
// decide whether to fire, and then update the firePdu. Hmmm, you might want a target to shoort at!
// etc. etc. your code goes here for your simulation of interest
// something happens between my simulation entities, la de da de da...
System.out.println ("... My simulation just did something, no really...");
// make your reports: narrative code for CommentPdu here (set all to empty strings to avoid sending)
narrativeMessage1 = "MV3500 ExampleSimulationProgramFisher_2";
narrativeMessage2 = "runSimulation() loop " + simulationLoopCount;
narrativeMessage3 = "this is working!"; // intentionally blank for testing
// your loop termination condition goes here
if (simulationLoopCount > 4) // for example
{
simulationComplete = true;
}
// =============================================================================================
// * your own simulation code is finished here! *
// =============================================================================================
// staying synchronized with timestep: wait duration for elapsed time in this loop
// Thread.sleep needs a (long) parameter for milliseconds, which are clumsy to use sometimes
Thread.sleep((long)(SIMULATION_LOOP_DURATION_SECONDS * 1000)); // seconds * (1000 msec/sec) = milliseconds
System.out.println ("... [Pausing for " + SIMULATION_LOOP_DURATION_SECONDS + " seconds]");
// OK now send the status PDUs for this loop, and then continue
System.out.println ("sending PDUs for simulation step " + simulationLoopCount + ", monitor loopback to confirm sent");
sendAllPdusForLoopTimestep(entityStatePdu_1, firePdu_1a, timeStepComment, narrativeMessage1, narrativeMessage2, narrativeMessage3);
sendSinglePdu(entityStatePdu_2); // me too i.e. 2!
System.out.println ("... [PDUs successfully sent for this loop]");
// ===============================
// loop now finished, check whether to terminate if simulation complete, otherwise continue
if (simulationComplete || (simulationLoopCount > 10000)) // for example; including fail-safe condition is good
{
sendSinglePdu(detonationPdu);
System.out.println ("... [Termination condition met, simulationComplete=" + simulationComplete + "]"); // ", final loopCount=" + loopCount +
break;
}
} // end of simulation loop
narrativeMessage2 = "runSimulation() completed successfully"; // all done
sendCommentPdu(narrativeComment, narrativeMessage1, narrativeMessage2, narrativeMessage3);
System.out.println ("... [final CommentPdu successfully sent for simulation]");
// TODO simulation management PDUs
}
catch (InterruptedException iex) // handle any exception that your code might choose to provoke!
{
Logger.getLogger(ExampleSimulationProgramFisher_2.class.getName()).log(Level.SEVERE, null, iex);
}
}
/* **************************** infrastructure code, modification is seldom needed ************************* */
String narrativeMessage1 = new String();
String narrativeMessage2 = new String();
String narrativeMessage3 = new String();
/* VariableRecordType enumerations have potential use with CommentPdu logs */
/* TODO contrast to EntityType */
VariableRecordType descriptionComment = VariableRecordType.DESCRIPTION;
VariableRecordType narrativeComment = VariableRecordType.COMPLETE_EVENT_REPORT;
VariableRecordType statusComment = VariableRecordType.APPLICATION_STATUS;
VariableRecordType timeStepComment = VariableRecordType.APPLICATION_TIMESTEP;
VariableRecordType otherComment = VariableRecordType.OTHER;
/**
* Output prefix to identify this class, helps with logging
*/
private final static String TRACE_PREFIX = "[" + ExampleSimulationProgramFisher_2.class.getName() + "] ";
// class variables
PduFactory pduFactory = new PduFactory();
DisThreadedNetworkInterface disNetworkInterface;
DisThreadedNetworkInterface.PduListener pduListener;
Pdu receivedPdu;
PduRecorder pduRecorder;
/**
* Constructor design goal: additional built-in initialization conveniences can go here
* to keep student efforts focused on the runSimulation() method.
*/
public ExampleSimulationProgramFisher_2()
{
// Constructor is under consideration. Constructor is not currently needed.
}
/**
* Utility Constructor that allows your example simulation program to override default network address and port
* @param address network address to use
* @param port corresponding network port to use
*/
public ExampleSimulationProgramFisher_2(String address, int port)
{
setNetworkAddress(address);
setNetworkPort(port);
}
/**
* @return the networkAddress
*/
public String getNetworkAddress()
{
return networkAddress;
}
/**
* @param newNetworkAddress the networkAddress to set
*/
public final void setNetworkAddress(String newNetworkAddress)
{
ExampleSimulationProgramFisher_2.networkAddress = newNetworkAddress;
}
/**
* @return the networkPort
*/
public int getNetworkPort()
{
return networkPort;
}
/**
* @param newNetworkPort the networkPort to set
*/
public final void setNetworkPort(int newNetworkPort)
{
ExampleSimulationProgramFisher_2.networkPort = newNetworkPort;
}
/**
* Initialize network interface, choosing best available network interface
*/
public void setUpNetworkInterface()
{
disNetworkInterface = new DisThreadedNetworkInterface(getNetworkAddress(), getNetworkPort());
disNetworkInterface.setDescriptor ("ExampleSimulationProgramFisher_2 pdu looping");
System.out.println("Network confirmation:" +
" address=" + disNetworkInterface.getAddress() + // disNetworkInterface.getMulticastGroup() +
" port=" + disNetworkInterface.getPort()); // + disNetworkInterface.getDisPort());
pduListener = (Pdu newPdu) -> {
receivedPdu = newPdu;
} /** Callback handler for listener */ ;
disNetworkInterface.addListener(pduListener);
String outputDirectory = DEFAULT_OUTPUT_DIRECTORY;
System.out.println("Beginning pdu save to directory " + outputDirectory);
pduRecorder = new PduRecorder(outputDirectory, getNetworkAddress(), getNetworkPort()); // assumes save
pduRecorder.setDescriptor ("ExampleSimulationProgramFisher_2 pduRecorder");
pduRecorder.start(); // begin running
}
/** All done, release network resources */
public void tearDownNetworkInterface()
{
pduRecorder.stop();
disNetworkInterface.removeListener(pduListener);
disNetworkInterface.close();
// disNetworkInterface.kill(); // renamed as close(), deprecated
// disNetworkInterface = null; // making sure no possibility of zombie process remaining...
}
/**
* Send a single Protocol Data Unit (PDU) of any type
* @param pdu the pdu to send
*/
private void sendSinglePdu(Pdu pdu)
{
try
{
disNetworkInterface.send(pdu);
Thread.sleep(100); // TODO consider refactoring the wait logic and moving externally
}
catch (InterruptedException ex)
{
System.err.println(this.getClass().getName() + " Error sending PDU: " + ex.getLocalizedMessage());
System.exit(1);
}
}
/**
* Send Comment PDU
* @see <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html">Passing Information to a Method or a Constructor</a> Arbitrary Number of Arguments
* @param commentType enumeration value describing purpose of the narrative comment
* @param comments String array of narrative comments
*/
public void sendCommentPdu(VariableRecordType commentType,
// vararg... variable-length set of String comments can optionally follow
String... comments)
{
sendAllPdusForLoopTimestep (null, null, commentType, comments);
}
/**
* Send EntityState, Fire, Comment PDUs that got updated for this loop, reflecting state of current simulation timestep.
* @see <a href="https://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html">Passing Information to a Method or a Constructor</a> Arbitrary Number of Arguments
* @param entityStatePdu the ESPDU to send, if any
* @param firePdu the FirePDU to send, if any
* @param commentType enumeration value describing purpose of the narrative comment
* @param comments String array of narrative comments
*/
public void sendAllPdusForLoopTimestep(EntityStatePdu entityStatePdu,
FirePdu firePdu,
VariableRecordType commentType,
// vararg... variable-length set of String comments can optionally follow
String... comments)
{
if (entityStatePdu != null)
sendSinglePdu(entityStatePdu);
if (firePdu != null)
sendSinglePdu(firePdu); // bang
if ((comments != null) && (comments.length > 0))
{
ArrayList<String> newCommentsList = new ArrayList<>();
for (String comment : comments)
{
if (!comment.isEmpty())
{
newCommentsList.add(comment); // OK found something to send
}
}
if (!newCommentsList.isEmpty())
{
if (commentType == null)
commentType = otherComment; // fallback value otherComment
// now build the commentPdu from these string inputs, thus constructing a narrative entry
CommentPdu commentPdu = pduFactory.makeCommentPdu(commentType, newCommentsList.toArray(new String[0])); // comments);
sendSinglePdu(commentPdu);
if (isVerboseComments())
System.out.println("*** [Narrative comment sent: " + commentType.name() + "] " + newCommentsList.toString());
}
}
}
/**
* Main method is first executed when a program instance is loaded.
* @see <a href="https://docs.oracle.com/javase/tutorial/getStarted/application/index.html">Java Tutorials: A Closer Look at the "Hello World!" Application</a>
* @param args command-line arguments are an array of optional String parameters that are passed from execution environment during invocation
*/
public static void main(String[] args)
{
System.out.println(TRACE_PREFIX + "started...");
ExampleSimulationProgramFisher_2 thisProgram = new ExampleSimulationProgramFisher_2(); // creates instance
// initial execution: can handle args array of initialization arguments here
if (args.length == 2)
{
if ((args[0] != null) && !args[0].isEmpty())
thisProgram.setNetworkAddress(args[0]);
if ((args[1] != null) && !args[1].isEmpty())
thisProgram.setNetworkPort(Integer.parseInt(args[1]));
}
else if (args.length != 0)
{
System.err.println("Usage: " + thisProgram.getClass().getName() + " [address port]");
System.exit(-1);
}
// OK here we go...
thisProgram.setUpNetworkInterface();
thisProgram.runSimulationLoops (); // ... your simulation execution code goes in there ...
thisProgram.tearDownNetworkInterface(); // make sure no processes are left lingering
System.out.println(TRACE_PREFIX + "complete."); // report successful completion
}
/**
* @return whether verboseComments mode is enabled
*/
public boolean isVerboseComments() {
return verboseComments;
}
/**
* @param newVerboseComments whether verboseComments mode is enabled
*/
public void setVerboseComments(boolean newVerboseComments) {
this.verboseComments = newVerboseComments;
}
}
This is a simple example simulation of two entities moving towards each other and then a detonation
occuring when they collide. This was simply to test a few different types of PDUs (entity, comment, fire, and
detonation) in order to become familiar for the final project.
Simple open Wireshark (or however you would like to caputre PDUs) and run the example simulation main class.
Output capture shows what should be seen on your screen as well as PDU capture logs.
File added
Written work on PDUs that would be useful in my community (infantry) as well as UPDATED
to include a PDU that could be of use here at NPS.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment