Simulation Listeners

From OpenRocket wiki
Revision as of 05:23, 10 March 2021 by Jddj (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

↑ Back to Contents

The current User's Guide is very much a work in progress, any help would be greatly appreciated!
If you'd like to contribute something, just hit the 'Edit' tab at the top.


This page describes features or examples introduced in OpenRocket version 1.1.6.
Earlier software versions may have different functionality or example designs.


Simulation listeners are an advanced way to monitor and interact with flight simulations while they are running. They work by defining a number of "hooks" of custom code which are called as various points during the simulation. OpenRocket allows full control of the rocket flight during the simulation. This enables simulating, for example, air-starts, active control mechanisms or calculating additional flight parameters on-the-fly.

Using simulation listeners requires basic Java knowledge and knowing how to use the command line.

The basic steps for implementing and using simulation listeners are the following:

  1. Implement the simulation listener in Java.
  2. Compile the Java class file.
  3. Start OpenRocket and include the class file in the classpath.
  4. Add the simulation listener to a simulation and run the simulation.

The example below will show these steps in detail.


Air-start launch example

The following example demonstrates how to simulate an air-start launch that launches from a height of 1000 meters.

First we need to implement the simulation listener in Java. The implementation is as below, stored in the file "AirStart.java":

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import net.sf.openrocket.simulation.SimulationStatus;
import net.sf.openrocket.simulation.exception.SimulationException;
import net.sf.openrocket.simulation.listeners.AbstractSimulationListener;
import net.sf.openrocket.util.Coordinate;

/**
 * Simulation listener that launches a rocket from a specific altitude.
 */
public class AirStart extends AbstractSimulationListener {

    /** Launch altitude in meters */
    private static final double ALTITUDE = 1000.0;

    @Override
    public void startSimulation(SimulationStatus status) throws SimulationException {
        Coordinate position = status.getRocketPosition();
        position = position.add(0, 0, ALTITUDE);
        status.setRocketPosition(position);
    }

}


Lines 1-4 have the necessary class imports for using the OpenRocket classes.

Line 9 defines the AirStart class. The class extends the AbstractSimulationListener class, which is the recommended way of defining simulation listeners. This allows better future compatibility, and allows you to override and implement only the methods relevant to your needs.

Line 12 defines a constant which has the launch altitude. OpenRocket does not currently support configuring simulation listeners, so all properties of the listener need to be hard-coded or read from some external source.

Lines 14-15 override the startSimulation method. This method is called at the beginning of a simulation. It is the proper place for setting up initial conditions for the simulation. The method takes a SimulationStatus object as an argument, which contains all details of the rocket's position, orientation and movement as well as all simulation details. This can be freely modified to suit the customization needs.

Lines 16-18 contain the actual air-start implementation. On line 16 we get the current rocket position as a three-dimensional cartesian coordinate (which should be the origin (0,0,0)). On line 17 we add the launch altitude to the Z-axis, which corresponds to altitude above ground. Finally on line 18 we set the position back into the SimulationStatus object.

After the listener has been implemented, it needs to be compiled into a Java class file. This requires providing the OpenRocket application on the classpath so that the compilation dependencies are met. Assuming that the OpenRocket JAR file and the AirStart.java file are both in the current directory, the file can be compiled for example on the command line with:

$ javac -cp OpenRocket-1.1.6.jar AirStart.java 

This will produce AirStart.class, which is the compiled class file.

Next we need to start OpenRocket with the directory containing the class file included on the classpath. The startup class needs to be explicitly defined, because using the -jar option would override the classpath set on the command line. From the command line:

$ java -cp OpenRocket-1.1.6.jar:. net.sf.openrocket.startup.Startup

Finally we need to add the simulation listener to a simulation. Open the Three-stage rocket example design. Create a new simulation which uses the [C6-5; B6-0; B6-0] motor configuration. Then open the Simulation options tab, and click Add under Simulation listeners. Type in AirStart, click OK and run the simulation.

You should get an apogee altitude between 1400-1500 meters. When you plot the simulation the rocket starts from an altitude of 1000 meters, rises to about 1450 meters and finally lands to 0 meters.

A slightly enhanced version of the air-start simulation listener is included in the OpenRocket package and can be used directly with the name net.sf.openrocket.simulation.listeners.example.AirStart. The source code is available in SVN.


Simulation listener actions

The simulation listeners can take action and modify the rocket state at any of the following (method names included in parenthesis):

  • before and after the simulation (startSimulation, endSimulation)
  • before and after a single step of the simulation (preStep, postStep)
  • before adding a flight event to the event queue (addFlightEvent)
  • before handling a flight event (handleFlightEvent)
  • before any motor ignition (motorIgnition) or recovery device deployment (recoveryDeviceDeployment)
  • before and after any computation (preXyz, postXyz)

All simulation listeners must implement the SimulationListener interface. This defines a few basic hooks for the simulation startup and steps. For additional hooks the class can additionally implement the SimulationEventListener and SimulationComputationListener interfaces.

The recommended way of implementing simulation listeners is by extending the AbstractSimulationListener class. This implements all of the hook methods with abstract implementations that do nothing. During future development the interfaces may be augmented or change slightly, but the abstract class will contain backward-compatible callbacks.

The hook methods come in three varieties depending on the return value.

  • The startSimulation, endSimulation and postStep are hooks that are called at a specific point of the simulation. They are void methods and do not return any value.
  • The preStep and event-related hooks return a boolean value indicating whether the action should be taken or not. A return value of true indicates that the action should be taken as normally would be (default), false will inhibit the action.
  • The pre- and post-computation methods may return the computed value, either as an object or a double value. The pre-computation methods allow pre-empting the entire computation, while the post-computation methods allow augmenting the computed values. These methods may return null or Double.NaN to use the original values (default), or return an overriding value.

Every method receives a SimulationStatus object as the first argument, and may have additional arguments. The SimulationStatus object contains information about the rocket's current position, orientation, velocity and simulation state. It also contains a reference to a copy of the rocket design and its configuration. Any simulation listener method may modify the state of the rocket by changing the properties of the state object.

Each listener method may also throw a SimulationException. This is considered an error during simulation, and an error dialog is displayed to the user with the exception message. The simulation data thus far is not stored in the simulation. Throwing a RuntimeException is considered a bug in the software and will result in a bug report dialog.

If a simulation listener wants to stop a simulation prematurely without an error condition, it needs to add a flight event of type SIMULATION_END to the simulation event queue:

status.getEventQueue().add(new FlightEvent(FlightEvent.Type.SIMULATION_END, status.getSimulationTime(), null));

This will cause the simulation to be terminated normally.



↑ Back to Contents