/** * 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 } }