Using Procedures

Top  Previous  Next

FreeFlyer script allows users to define subroutines, called Procedures, to execute generic sets of FreeFlyer script. This functionality allows users to more easily generate and maintain complex Mission Plans.


There are a variety of Sample Mission Plans (included with your FreeFlyer installation) that demonstrate various applications of these topics. Continue to one of the Mission Plans listed below to view descriptions and images of these examples.


FreeFlyer Scripting Samples

Matrix Multiplication Procedures


Interfacing with External Resources Samples

Using Externals

Using Globals


Interplanetary Samples

Lambert Transfer Calculation


Maneuvering Samples

Mass Properties Report



Kalman Filter OD - Lunar TDRS Relay



Place common blocks of script in Procedures

Streamlines a Mission Plan by replacing reoccurring code snippets with a Call to a Procedure

Code snippets are located in one location for easy maintenance such as debugging or functionality enhancements




Procedures may be defined in the Mission Plan or in an external .FFProcedure file. See the Include command for more information.

Procedures are accessed using a Call command.

Procedures are defined using a Define Procedure command.

Arguments must be passed into a Procedure in order to retrieve calculations and store their results.

Structs (user-defined collections of related FreeFlyer objects) can be passed as arguments into Procedures, effectively passing several objects together as one argument.

Argument types for corresponding Call and Define statements must match and must be in the same sequence.

Argument names for corresponding Call and Define statements are NOT required to match.


The Include Command

The Include command is used to allow Mission Plan access to the Procedure.

Not necessary if the Procedure is added to the Externals list. The Externals tab is discussed on the Control Screen section of the Tour of FreeFlyer.

See the Parsing Arbitrary String Data page for information on including environment variables in an Include statement.


Include "filename";


Where "filename" is the valid OS described path and file name, including the extension, of your Procedure.


The Call Command

The Call command is used with the following syntax from within the Mission Sequence. This example calls a Procedure named "Procedure1" while passing both a Spacecraft and its tank into the Procedure:


Call Procedure1(Spacecraft1, Spacecraft1.Tanks[0]);


The argument types that are used in the Call command MUST match the types used in the Define Procedure line, otherwise a syntax error will appear.


The Define Procedure Command

The Define Procedure command is coupled with an EndProcedure statement.

Must be present in the following format as the first line in a Procedure.

The example below defines a Procedure named "Procedure1" while receiving both a Spacecraft and its tank from the Call statement:


Define Procedure Procedure1(Spacecraft Spacecraft1, SphericalTank Tank1);
     // ...


At this point, the properties of the Spacecraft and Tank are transferred from the Procedure back to the Mission Plan.


The ExitProcedure Command

The ExitProcedure command can be used within a Procedure to cause the Procedure to exit without completing the rest of the commands contained in the Procedure. This can be useful if a certain value is outside the expected range. In the example below, a Procedure is defined with a Spacecraft as an argument. If the eccentricity of the Spacecraft's orbit is greater than 0.2, the Procedure will exit; otherwise it will continue through the Procedure.


Define Procedure ExitProcTest(Spacecraft sc);


     If (sc.E > 0.2);



          // Enter the desired script here...






Details on Procedure Implementation

A few additional details of FreeFlyer's implementation of the Procedure functionality are worth noting:


FreeFlyer only supports the typical Procedure functionality. This means that the algorithm within the Procedure cannot return a value. Although this might seem limiting at first, the approach for having a Procedure calculate or evaluate a return status is to simply pass an Argument to hold that data.


All Arguments are passed into the Procedure using the "pass-by-reference" method. This means that the reference to an object in the Argument list is passed along to the Procedure, as opposed to having the Procedure instantiate a new copy of the object, and using that cloned object for the operations it performs. The effect of this is that any operation that a Procedure may execute on the list of Arguments will be seen after having completed execution of the Procedure. A simple example would be to change the color of the spacecraft based on the True Anomaly of its state.


The local variables within a Procedure do not maintain their values between subsequent calls to the Procedure unless the Procedure is called inside of a For or While loop. In the example below, a Procedure is defined that creates a Variable a, reports a, and then sets its value to 5. When the Persistence Procedure is called within the For loop for the first time, the Report will show a value of 0 for a. Subsequent calls to the Persistence Procedure within the For loop will Report a value of 5 because a has persisted from the previous call (Arrow #1). The Call to Persistence outside of the For loop will create the Variable a and set its value to 0 (Arrow #2); the value will not persist from the previous instance of Persistence called inside of the For loop.


Define Procedure Persistence();

    Variable a;

     Report a;

    a = 5;



Variable i;

For i = 0 to 2;

     Call Persistence(); // Arrow #1



Call Persistence(); // Arrow #2


Report output for Persistence procedure called within a For loop. 

Report output for Persistence procedure called within a For loop.


Report output for Persistence procedure called outside of a For loop.

Report output for Persistence procedure called outside of a For loop.


There is no mechanism to prototype a Procedure. Prototyping provides a mechanism to specify the calling interface to a Procedure without having to define the executive behavior of the Procedure. The limitation of the lack of prototyping has two key consequences; one, a Procedure must be fully defined before it is referenced in FreeFlyer Script; two, since a Procedure must be fully defined before it is used, there is no way to support a recursive Procedure.


FreeFlyer supports global Variables, Arrays, Strings, and StringArrays. See the Constant and Global Keywords article for more information.


Global Variable v;
Global Array a[0];
Global String Status;
Global StringArray State[6];


When you pass an argument to a Procedure that evaluates to a string, number, array, or string array but is not a String object, Variable object, Array object, or StringArray object, FreeFlyer will create temporary objects with the same values you passed. However, if you do this, any changed values are NOT copied on the way back out. Using this method to provide input data is fine, but if you’re trying to get new data out of the Procedure, you’ll need to pass the actual object. The following example shows why it works this way:


Define Procedure example(Variable x);

x = 5;


Now, suppose this Procedure was called using an expression that evaluates to a variable, instead of an actual Variable object:


Call example(1 + 2*3);

There is nowhere to assign the value, which is a problem. We allow users to pass compound expressions as inputs for convenience, but since FreeFlyer doesn’t determine if a particular argument to a procedure will be used as an input or an output, the user is responsible for passing an actual object for output arguments, and not any kind of expression. Another example of this behavior is shown in the ChangeName Procedure below.


Define Procedure ChangeName(String name);

   name = "newName";



The Procedure takes in String as an argument. Calling the ChangeName Procedure with Spacecraft1.Name as the argument will not assign "newName" to Spacecraft1.Name outside the Procedure. Instead, a String object would need to be passed to the Procedure and Spacecraft1.Name would need to be set to that String after the Procedure call as in the second example below.


Call ChangeName(Spacecraft1.Name); // the string Spacecraft1.Name will not be assigned the "newName" string


String SpacecraftName;

Call ChangeName(SpacecraftName);

Spacecraft1.Name = SpacecraftName;


The @ symbol can be used to scan a literal string in an Include statement for environment variables and escape sequences. The $(EnvironmentVariableName) sequence inside a literal string indicates that the specified environment variable will be evaluated at parse time. While the Include command will always be evaluated at parse time, if you are using an environment variable for another purpose, you can also retrieve it at runtime using the FF_Preferences.GetEnvironmentVariable("EnvironmentVariableName") method. See the Parsing Arbitrary String Data page for more information.

Include @"$(myEnvironmentVariableToProcedureDirectory)\\myProcedure.FFProcedure";



More Examples

Example: Changing the color of a Spacecraft

Example: Setting Spacecraft Orientation


Example: Creating a Report


Example: Generating Ephemeris



See Also

Define Procedure Command

Include Command

Call Command

Structs Script Reference