Analysis Tool Controllers

As its name suggests, an AnalysisToolController is what controls an analysis tool. Each delegate is associated with a specific analysis tool controller, which is in turn responsible for instantiating all of its delegates before the start of the simulation. Each controller is responsible for injecting any dependencies from the external analysis tool into the delegates at runtime. In the case of STK, this would include data about STK objects and other global analysis objects. For a custom tool, it could be any ambient or object-specific data relevant to that particular delegate instance. For more on how to inject this data, see the section on injection constructors.

The AnalysisToolController implementation class is instantiated by reflection. It must either have a public no-argument constructor or a public constructor with the @Inject annotation. The BuiltInAnalysisToolController constructor also accepts the MoxieSimulation configuration settings provided in the SysML, which specify the analysisStartTime and analysisStopTime values for the simulation.

For most applications that do not require special tool customizations, using the BuiltInAnalysisToolController is sufficient. It is entirely possible to connect to external tools using the BuiltInAnalysisToolController, but only if all the necessary information is provided directly in data defined in the SysML elements.

If you are using STK as your analysis tool, you can inject instructions into the StkController using a stereotype to spawn a new instance of STK, create a new scenario, or load an existing scenario at the start of a simulation. Check out STK Stereotypes for more information.

BuiltInAnalysisToolController also implements the following methods from the AnalysisToolController interface:

  • getValidInterval - The Moxie Engine calls this to retrieve the time interval over which the analysis tool can simulate. The Moxie Engine combines this interval with the intervals from other analysis tools specified in separate delegate modules and feeds the combined interval back to this instance via createDelegateDependencyProvider.
  • createDelegateDependencyProvider - The Moxie Engine calls this once the simulation interval has been determined. The returned DelegateDependencyProvider participates in the delegate instantiation process. It provides additional values that can be passed to the constructors of those delegate instances.
  • updateSimulationTime - This is a callback that is invoked when the engine advances the simulation time.

You can apply most of the implementations shown above to any simulation. More advanced simulations may require additional custom logic. Feel free to use the code shown in this reference or in the sample source code supplied in the Moxie installation as a starting point. Moxie includes two AnalysisToolController implementations, which you can take advantage of right away: BuiltInAnalysisToolController and StkController.

Built-in controller dependencies

The createDelegateDependencyProvider method in AnalysisToolController can provide constructor dependencies for delegate instances. In addition to those provided by the specific AnalysisToolController, some values are provided by default:

Dependency (shown as a constructor injection parameter) Description
@InjectByName("timeProvider")
TimeProvider timeProvider

The TimeProvider is the single source of truth for the progression of time throughout the simulation. It represents the 'clock' of a simulation, defining the current simulation time for all events and other AnalysisToolController implementations.

In this snippet, the timeProvider is being used in a BasicProperty to inform the simulation when the passenger is satisfied with a photo. The BasicProperty uses the timeProvider when keeping track of the exact times during execution when the property's value changes.

mIsSatisfiedWithPhoto = new BasicProperty<Boolean>(timeProvider, false);
@InjectByName("moxieUnitConverter")
MoxieUnitConverter unitConverter

The MoxieUnitConverter is a utility class that provides the means of converting an instance of javax.measure.Quantity to a different kind of unit. A Quantity represents the Java equivalent of a SysML value type containing a "quantity kind" and a "unit". Quantity and MoxieUnitConverter serve to help Java delegate authors manipulate these values from the Java code while ensuring consistency between the units in the SysML model and the units required by the analysis code. Quantity comes from the "Units of Measurement" 2.0 API in JSR-385. For more details, see the section on using Units under Properties and Operations.

You can find more information about the "Units of Measurement" 2.0 API in JSR-385 at https://unitsofmeasurement.github.io/pages/about.html.

@InjectByName("stateMachineRemoteControl")
StateMachineRemoteControl stateMachineRemoteControl

Provides manual control over sending call events and signal events to state machine sessions from within operations. When using @AutoDelegateImplementation, the autogenerated code will handle triggering call events automatically, even if a concrete implementation is provided. Therefore, you only need this dependency when manually implementing an entire delegate class or for manually sending signal events. Otherwise, there is no need to inject this in your constructor.

Here is an example of sending a signal event using the stateMachineRemoteControl:

stateMachineRemoteControl.sendSignalEvent("Structure::Passenger::BuckleUp", target);
@InjectByName("delegateInstanceManager")
DelegateInstanceManager delegateInstanceManager

Provides a mechanism for instantiating new Java delegate objects and SysML instance specifications during simulation. The classifier behaviors for each newly created delegate instance will start immediately after it is created. The DelegateInstanceManager also enables delegate authors to assign both values for the instance's slots and custom stereotypes for the instance itself. This is especially useful for cases where simulations require a large number of objects parameterized by other objects in the scenario. For instance, when defining the parameters of a large satellite constellation or a group of drones forming a swarm, it can be useful to create each individual instance programmatically at runtime rather than creating separate SysML instance specifications for hundreds of individual objects.

Here is an example of creating a new instance with initialized slots and a custom stereotype:

@AutoDelegateImplementation
@DelegateFor("Structure::CustomBlock")
class MyCustomBlock{
    private DelegateInstanceManager delegateInstanceManager;
    private final BasicProperty<MyCustomBlock> child;

    public MyCustomBlock(@InjectByName("delegateInstanceManager") DelegateInstanceManager instanceManager) {
        delegateInstanceManager = instanceManager;
        //"name", "setting", and "child" Properties will be initialized during Wire-Up
    }

    public void callThisOperationFromSysMLToCreateNewInstanceOfMyself(){
        MyCustomBlock newObject = delegateInstanceManager.create(MyCustomBlock.class)
            .withSlotValue("name", "doppelganger")
            .withSlotValue("setting", 42)
            .withStereotypeInstance(new MyCustomStereotype("hello world!"))
            .spawnNewInstance();
        child.setValue(newObject);
    }
}

@StereotypeImplementationFor("Configuration::CustomStereotype")
class MyCustomStereotype{
    private String tag;
    public MyCustomStereotype(@InjectByTag("tag") String newTag){ tag = newTag; }
    String getValue(){ return tag; }
}
@NotNull @InjectByName("instanceName")
String instanceName
Provides the name of the instance that this Java object represents. This is useful when multiple instances of the same type participate in a simulation, as it allows you to differentiate among them. In most cases, the instance name will be the name specified in the SysML instance specification. In cases where new objects are created at runtime without an instance specification, however, the instance name may not correspond to anything in the saved model.
@NotNull @InjectByName("randomNumberGenerator")
RandomNumberGenerator randomGen
Provides utility functions for pseudo-random generated numbers within inclusive ranges. It also supports uniformly distributed random numbers in double, int, and float types. It further supports Gaussian-distributed random numbers in double or int types with specific standard deviations and mean values. In addition, it allows for seed selection through the Moxie-Base::Configuration::MoxieStochasticSettings stereotype.
@InjectByName("simulationLogger")
SimulationLogger simulationLogger

The SimulationLogger provides you with the ability to log custom messages to the simulation log file and console.

In this snippet, the simulationLogger is being used to log a message when the balloon is launching.

mLogger.info("Launching balloon.");

STK controller dependencies

The StkController adds some delegate dependencies beyond those that are built in.

Dependency (shown as a constructor injection parameter) Description
@NotNull @InjectByName("stkToolbox")
StkToolbox toolbox

The StkToolbox contains utility methods for interacting with the instance of STK that is supporting the current simulation. It also provides access to the StkObjectModel through IAgStkObjectRoot. The StkObjectModel is also exposed through the StkApplication dependency shown below. Moxie supports only one instance of STK per simulation. See StkToolbox for more information.

The following snippet creates and returns a new STK Aircraft Object:

stkAircraft = toolbox.getRoot().getCurrentScenario().getChildren().
    _new(AgESTKObjectType.E_AIRCRAFT, instanceName);

@NotNull @InjectByName("stkEarth")
StkEarth earth

Provides access to the default representation of Earth inside of STK. In particular, for space-domain operations, it provides information about the inertial and fixed frames exposed as part of the Moxie model libraries.

The earth object provides well-known reference frames for use in analysis inside STK.

earth.getInternationalCelestialReferenceFrame();
earth.getFixedReferenceFrame();
@NotNull @InjectByName("stkApplication")
StkApplication stkApplication

While most interactions with STK happen through the StkToolbox detailed above, StkApplication provides access to the STK application instance in situations when the simulation requires closing, loading, or creating new STK scenarios. If other objects require access to specific STK object paths, closing the existing STK scenario may cause those objects to become invalid. Since there is not a particular order in which objects are instantiated, ensure STK application-level operations occur at well-known times in a simulation, ideally before using any STK Objects within the scenario. Lastly, while this provides some simple operations for interacting with STK, you can perform additional tasks using stkApplication.getCurrentScenario().getRootObject().

The following snippet will start and attach to a new instance of STK and load a blank scenario called "BalloonRide":

StkApplication stkApplication = StkApplication.createNewInstance("BalloonRide");
@Nullable @InjectByName("stkObject")
IAgStkObject stkObject

Provides access to the STK object in the current scenario with the path specified in the stkObjectPath tag of the Moxie-STK::Configuration::MoxieStkExistingObject stereotype.

In this snippet, the StkSpatialPoint adapts the "Center" from the STK object stkObject (the stkAircraft) into an actual SpatialPoint from the Moxie model libraries:

IAgStkObject stkAircraft = stkObject;
mCenter = new StkSpatialPoint(
    toolbox,
                              timeProvider,
                              stkAircraft,
                              earth.getInternationalCelestialReferenceFrame().getReferenceAxes());
@Nullable @InjectByName("stkObjectPath")
String stkObjectPath
Provides the path to the STK object for this instance as specified in the stkObjectPath tag of the Moxie-STK::Configuration::MoxieStkExistingObject stereotype applied to the SysML object instance.
@Nullable @InjectStereotype MoxieStkExistingObject
stkObjectConnection
Provides the stereotype data from the Moxie-STK::Configuration::MoxieStkExistingObject stereotype applied to the SysML object instance.
@Nullable @InjectStereotype MoxieStkFixedStepSampling
stkSampling
Provides the stereotype data from the Moxie-STK::Configuration::MoxieStkFixedStepSampling stereotype applied to the SysML object instance.

For more details on using STK objects, see STK Programming Help.