From b304c25beaccb296234cb1baf176cb93fdb29305 Mon Sep 17 00:00:00 2001 From: brutzman <brutzman@nps.edu> Date: Thu, 23 Dec 2021 16:29:04 -0800 Subject: [PATCH] initial stub program subclassing ExampleSimulationProgram --- .../ExampleTrackInterpolation.java | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 examples/src/OpenDis7Examples/ExampleTrackInterpolation.java diff --git a/examples/src/OpenDis7Examples/ExampleTrackInterpolation.java b/examples/src/OpenDis7Examples/ExampleTrackInterpolation.java new file mode 100644 index 0000000000..8c15c558b6 --- /dev/null +++ b/examples/src/OpenDis7Examples/ExampleTrackInterpolation.java @@ -0,0 +1,183 @@ +/** + * 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 brutzman@nps.edu + */ +package OpenDis7Examples; + +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.ForceID; +import edu.nps.moves.dis7.pdus.EntityID; +import edu.nps.moves.dis7.pdus.EntityStatePdu; +import edu.nps.moves.dis7.pdus.FirePdu; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * The purpose of this program is to provide an easily modifiable example + * simulation for networked entity tracks and presentation, including + * DIS-capable entities doing tasks and reporting them to the network. Default + * settings include PDU recording turned on by default. + */ +public class ExampleTrackInterpolation extends ExampleSimulationProgram { + + /** + * Output prefix to identify this class (override in subclass), helps with + * logging + */ + private final static String TRACE_PREFIX = "[" + ExampleTrackInterpolation.class.getName() + "] "; + + /** + * This runSimulationLoops() method is 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 + @Override // indicates that this method supercedes corresponding superclass method + public void runSimulationLoops() { + try { + final int SIMULATION_MAX_LOOP_COUNT = 10; // be deliberate 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 + simulationTime = initialTime - currentTimeStep; // pre-initialization for first loop + + // 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_1.setSiteID(1).setApplicationID(2).setEntityID(4); // made-up example ID; + // 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_1.setEntityType(new _001Poseidon()); // note import statement above + + EntityStatePdu entityStatePdu_2 = pduFactory.makeEntityStatePdu(); + entityStatePdu_2.setEntityID(entityID_2); + entityStatePdu_2.setForceId(ForceID.OPPOSING); + entityStatePdu_2.setEntityType(new _002Triton()); // note import statement above + + 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? + + // TODO simulation management PDUs for startup, planning to design special class support + // 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 + simulationTime += currentTimeStep; // good practice: update clock along with loop index + + // ============================================================================================= + // * 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_1.setTimestamp(simulationTime); + + // decide whether to fire, and then update the firePdu. Hmmm, you might want a target to shoot 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 TrackSimulationProgram"; + narrativeMessage2 = "runSimulation() loop " + simulationLoopCount + " at time " + simulationTime; + narrativeMessage3 = ""; // 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) (currentTimeStep * 1000)); // seconds * (1000 msec/sec) = milliseconds + System.out.println("... [Pausing for " + currentTimeStep + " 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 + { + 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(ExampleTrackInterpolation.class.getName()).log(Level.SEVERE, null, iex); + } + } + + /* Default constructors used unless otherwise defined/overridden. */ + /** + * 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 + "main() started..."); + + ExampleTrackInterpolation thisProgram = new ExampleTrackInterpolation(); // creates instance within static main() method + + // initial execution: 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().getSimpleName() + " [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 + } + +} -- GitLab