Something went wrong on our end
-
ethanjwilliams authoredethanjwilliams authored
ExampleSimulationProgram.java 11.71 KiB
/**
* Copyright (c) 2008-2024, MOVES Institute, Naval Postgraduate School (NPS). All rights reserved.
* This work is provided under a BSD open-source license, see project license.html or license.txt
*
* This main class is my submission for HW 3.
*
* @author ethanjwilliams
*/
package MV3500Cohort2024JulySeptember.homework3.Williams;
import edu.nps.moves.dis7.entities.swe.platform.surface._001Poseidon;
import edu.nps.moves.dis7.entities.swe.platform.surface._002Triton;
import edu.nps.moves.dis7.enumerations.*;
import edu.nps.moves.dis7.pdus.*;
import edu.nps.moves.dis7.utilities.DisChannel;
import edu.nps.moves.dis7.utilities.PduFactory;
import java.time.LocalDateTime;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The purpose of this inheritable class is to provide an easily modifiable
* example simulation program that includes DIS-capable entities performing
* tasks of interest, and then reporting activity via PDUs to the network.
* Default program initialization includes PDU recording turned on by default.
*
* Homework 3 networking choices:
* This simulation uses UDP multicast for efficient distribution of PDUs to
* multiple participants, which is great for large-scale simulations where
* state updates need to reach all networked participants. UDP is chosen over
* TCP due to its lower latency, which is essential for real-time simulations.
*
* @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramLog.txt" target="_blank">ExampleSimulationProgramLog.txt</a>
* @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramPduCaptureLog.dislog" target="_blank">ExampleSimulationProgramPduCaptureLog.dislog</a>
* @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramFlowDiagram.pdf" target="_blank">ExampleSimulationProgramFlowDiagram.pdf</a>
* @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramWireshark.png" target="_blank">ExampleSimulationProgramWireshark.png</a>
* @see <a href="https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/examples/src/OpenDis7Examples/ExampleSimulationProgramSequenceDiagram.png" target="_blank">ExampleSimulationProgramSequenceDiagram.png</a>
*/
public class ExampleSimulationProgram
{
private String descriptor = this.getClass().getSimpleName();
protected DisChannel disChannel;
protected PduFactory pduFactory;
private double simulationTimeStepDuration = 1.0;
double simulationTimeInitial = 0.0;
double simulationTimeSeconds = simulationTimeInitial;
int MAX_LOOP_COUNT = 4;
String narrativeMessage1 = new String();
String narrativeMessage2 = new String();
String narrativeMessage3 = new String();
protected EntityID entityID_1 = new EntityID();
protected EntityID entityID_2 = new EntityID();
protected EntityStatePdu entityStatePdu_1;
protected EntityStatePdu entityStatePdu_2;
protected FirePdu firePdu_1a;
protected FirePdu firePdu_1b;
protected MunitionDescriptor munitionDescriptor1;
public ExampleSimulationProgram()
{
initialize();
}
public ExampleSimulationProgram(String newDescriptor)
{
descriptor = newDescriptor;
initialize();
}
public ExampleSimulationProgram(String address, int port)
{
disChannel.setNetworkAddress(address);
disChannel.setNetworkPort(port);
disChannel.setVerboseComments(true);
disChannel.setVerboseDisNetworkInterface(true);
disChannel.setVerbosePduRecorder(true);
initialize();
}
private void initialize()
{
initializeDisChannel();
initializeSimulationEntities();
disChannel.join();
String timeStepMessage = "Simulation timestep duration " + getSimulationTimeStepDuration() + " seconds";
disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_SIMULATION_TIMESTEP, timeStepMessage);
}
private void initializeDisChannel()
{
if (disChannel == null)
disChannel = new DisChannel();
else
{
disChannel.printlnTRACE ("*** warning, duplicate invocation of initializeDisChannel() ignored");
return;
}
pduFactory = disChannel.getPduFactory();
disChannel.setDescriptor(this.getClass().getSimpleName());
disChannel.setUpNetworkInterface();
disChannel.printlnTRACE ("just checking: disChannel.getNetworkAddress()=" + disChannel.getNetworkAddress() +
", getNetworkPort()=" + disChannel.getNetworkPort());
disChannel.getDisNetworkInterface().setVerbose(true);
disChannel.printlnTRACE ("just checking: hasVerboseSending()=" + disChannel.getDisNetworkInterface().hasVerboseSending() +
", hasVerboseReceipt()=" + disChannel.getDisNetworkInterface().hasVerboseReceipt());
disChannel.getPduRecorder().setVerbose(true);
}
public void initializeSimulationEntities()
{
if (pduFactory == null)
pduFactory = disChannel.getPduFactory();
entityStatePdu_1 = pduFactory.makeEntityStatePdu();
entityStatePdu_2 = pduFactory.makeEntityStatePdu();
firePdu_1a = pduFactory.makeFirePdu();
firePdu_1b = pduFactory.makeFirePdu();
munitionDescriptor1 = new MunitionDescriptor();
entityID_1.setSiteID((int)(Math.random() * 100))
.setApplicationID((int)(Math.random() * 100))
.setEntityID((int)(Math.random() * 100));
disChannel.addEntity(entityID_1);
entityID_2.setSiteID((int)(Math.random() * 100))
.setApplicationID((int)(Math.random() * 100))
.setEntityID((int)(Math.random() * 100));
disChannel.addEntity(entityID_2);
entityStatePdu_1.setEntityID(entityID_1);
entityStatePdu_1.setForceId(ForceID.FRIENDLY);
entityStatePdu_1.setEntityType(new _001Poseidon());
entityStatePdu_1.setMarking("Ethan's Poseidon #1");
entityStatePdu_2.setEntityID(entityID_2);
entityStatePdu_2.setForceId(ForceID.OPPOSING);
entityStatePdu_2.setEntityType(new _002Triton());
entityStatePdu_2.setMarking("Ethan's Triton #2");
munitionDescriptor1.setQuantity(1);
firePdu_1a.setDescriptor(munitionDescriptor1).setRange(1000.0f);
}
@SuppressWarnings("SleepWhileInLoop")
public void runSimulationLoops ()
{
try
{
final int SIMULATION_MAX_LOOP_COUNT = 10;
int simulationLoopCount = 0;
boolean simulationComplete = false;
String timeMessage = "Simulation time " + simulationTimeSeconds + " at LocalDateTime " + LocalDateTime.now();
disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_TIME, timeMessage);
while (simulationLoopCount < SIMULATION_MAX_LOOP_COUNT)
{
simulationLoopCount++;
entityStatePdu_1.getEntityLocation().setX(entityStatePdu_1.getEntityLocation().getX() + (Math.random() * 2));
System.out.println ("... My simulation just did something...");
System.out.flush();
narrativeMessage1 = "Ethan's Custom Simulation Program";
narrativeMessage2 = "Loop " + simulationLoopCount + " - MV3500 Custom Version";
narrativeMessage3 = "Simulation developed by Ethan Williams";
if (simulationLoopCount > MAX_LOOP_COUNT)
{
simulationComplete = true;
}
Thread.sleep((long)(getSimulationTimeStepDuration() * 1000));
System.out.println ("... [Pausing for " + getSimulationTimeStepDuration() + " seconds]");
sendAllPdusForLoopTimestep(simulationTimeSeconds,
entityStatePdu_1,
firePdu_1a,
DisChannel.COMMENTPDU_APPLICATION_STATUS,
narrativeMessage1, narrativeMessage2);
disChannel.sendSinglePdu(simulationTimeSeconds, entityStatePdu_2);
System.out.println ("... [PDUs of interest successfully sent for this loop]");
System.out.flush();
if (simulationComplete || (simulationLoopCount > 10000))
{
System.out.println ("... [loop termination condition met, simulationComplete=" + simulationComplete + "]");
System.out.flush();
break;
}
simulationTimeSeconds += getSimulationTimeStepDuration();
}
narrativeMessage2 = "runSimulation() completed successfully";
disChannel.sendCommentPdu(DisChannel.COMMENTPDU_NARRATIVE, narrativeMessage1, narrativeMessage2, narrativeMessage3);
System.out.println ("... [final=completion CommentPdu successfully sent for simulation]");
disChannel.leave();
}
catch (InterruptedException iex)
{
Logger.getLogger(ExampleSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex);
}
}
public void sendAllPdusForLoopTimestep(double simTimeSeconds,
EntityStatePdu entityStatePdu,
FirePdu firePdu,
VariableRecordType commentType,
String... comments)
{
if (entityStatePdu != null)
disChannel.sendSinglePdu(simTimeSeconds, entityStatePdu);
if (firePdu != null)
disChannel.sendSinglePdu(simTimeSeconds, firePdu);
disChannel.sendCommentPdu(simTimeSeconds, commentType, comments);
}
protected void handleArguments (String[] args)
{
if (args.length == 2)
{
if ((args[0] != null) && !args[0].isEmpty())
thisProgram.disChannel.setNetworkAddress(args[0]);
if ((args[1] != null) && !args[1].isEmpty())
thisProgram.disChannel.setNetworkPort(Integer.parseInt(args[1]));
}
else if (args.length != 0)
{
System.err.println("Usage: " + thisProgram.getClass().getSimpleName() + " [address port]");
System.exit(-1);
}
}
public String getDescriptor() {
return descriptor;
}
public void setDescriptor(String newDescriptor) {
if (newDescriptor == null)
newDescriptor = "";
this.descriptor = newDescriptor;
}
public double getSimulationTimeStepDuration() {
return simulationTimeStepDuration;
}
public void setSimulationTimeStepDuration(double timeStepDurationSeconds) {
this.simulationTimeStepDuration = timeStepDurationSeconds;
}
protected static ExampleSimulationProgram thisProgram;
public static void main(String[] args)
{
thisProgram = new ExampleSimulationProgram("test constructor");
thisProgram.disChannel.printlnTRACE("main() started...");
thisProgram.handleArguments(args);
thisProgram.runSimulationLoops();
thisProgram.disChannel.tearDownNetworkInterface();
thisProgram.disChannel.printlnTRACE("complete.");
System.exit(0);
}
}