Tips and Tricks for Designing a Constellation in FreeFlyer®

March 27, 2020

FreeFlyer is a powerful astrodynamics software tool that gives the user the power to model satellite constellations of any size; whether it be pre-launch mission analysis or nominal operations and flight dynamics support, FreeFlyer powers your constellation’s design, analysis, and operations. There are many tips and tricks that a user can employ to more effectively design and analyze constellations of any size, in any orbit regime, even around any planet! Here are a few of our favorite suggestions for maximizing FreeFlyer’s utility – if you already knew most of these, consider yourself a power user!

Tricks for Mission Plan Optimization

Use Mean Element Sets

For large-scale constellations, it is often necessary to choose initial states very carefully in order to reduce the need for station-keeping maneuvers as the orbits evolve. Therefore, we always recommend using a mean element set like J2 Brouwer-Lyddane rather than Keplerian elements. The Brouwer-Lyddane mean elements account for realistic perturbations to Earth’s gravity model and are constructed based on an average over time and therefore have a more stable period. Whereas, Keplerian osculating elements are purely instantaneous values that treat the orbit as a classical two-body system; that is, they assume that the central body can be represented as a point mass. So, when using Keplerian elements for initialization, with a high-fidelity force model, the elements will vary significantly even over the course of a single orbit. Initializing a constellation’s orbits using Keplerian elements will result in different orbit periods for different satellites in your constellation, leading the satellites to drift relative to each other over time.

Tune the Fidelity of Your Force Model

If you do not need a high-fidelity analysis, it is more efficient to configure your force model to the relative fidelity of the analysis. This includes choosing optimal Integrators for propagation to decrease runtime and significantly improve FreeFlyer’s performance. Users can review detailed information on a specific integrator and the advantages versus disadvantages using the “Choosing an Integrator” page of our Help File. Note: If you are pre-computing your orbit and saving off ephemeris files, then a higher fidelity force model can be used since the ephemerides only need to be computed once.”

Pre-compute Orbit Propagation

A simple way to increase your Mission Plan’s performance is to pre-compute a Formation’s orbit propagation and save states to an ephemeris file. Once the ephemerides for the Formation are created you can run an additional Mission Plan that use the ephemerides for propagation. This allows you to compute multiple orbit products, for example contact analysis, Pc calculations, and ShadowTimes using the ephemerides rather than re-integrating the orbit propagation. This is especially beneficial when executing these Interval method analyses for a Formation, as it helps in reducing the Mission Plan runtime and RAM usage.

Iridium Constellation

Figure 1: Iridium Constellation

Use the Profiler

If you are interested in making sure your code is efficient and not wasting compute cycles in unnecessary ways you can use the built-in FreeFlyer profiler to review your Mission Plan’s code execution. The profiler reports information about how much time is spent in different sections of a Mission Plan. After you run a Mission Plan through the profiler, timing information is reported to a scopes file (time per scope such as a procedure) and a lines file (time per line). With this profiler knowledge you can better debug and optimize Mission Plans. An example of using this command line switch can be found in the FreeFlyer Help File guide for the profiler.

Utilize Multiple Instances of FreeFlyer

You can optimize a Mission Plan by splitting a process across your computer’s multiple cores. A FreeFlyer license provides the ability to launch up to 6 instances of FreeFlyer at a time, so you can spread out your simulation’s functionality across your available cores to improve runtime. This is accomplished by running multiple copies of the same Mission Plan at the same time, then passing inputs to the Mission Plan so that each instance of FreeFlyer works on a portion of the problem.

Use the Runtime API

To help decrease runtime, you can also split a problem across multiple cores using the FreeFlyer Runtime API (RTAPI) to control the automation for executing processes via a common developer language. The API supports the following languages:

  • C/C++
  • C#
  • Java
  • Python
  • Matlab

The RTAPI interfaces can help to cut down on the amount of code needed within a Mission Plan by executing basic functionality using the chosen development language. The Runtime API also includes Asynchronous Programming to more easily split a process across cores.

ViewWindow Efficiency

To improve performance with extremely large Formations, we recommend viewing them in a ViewWindow as a group. When you View a Formation as a Group, FreeFlyer represents each Spacecraft as a dot without drawing the tail to optimize the performance.

Formation myFormation;
ViewWindow ViewWindow1 ({myFormation});

myFormation.LoadNoradTLE(“GPS Fleet.tle”);
myFormation.ViewAsGroup = 1; // 1 = View all Spacecraft as a group
myFormation.GroupPointSize = 10;

While (myFormation[0].ElapsedTime < TIMESPAN(6 hours));
Update ViewWindow1;

Formation ViewAsGroup

Figure 2: Formation ViewAsGroup Example

Top: View each Spacecraft individually (Runtime of 20 secs)

Bottom: View the Formation as a group (Runtime of 7 secs)

Binary Ephemeris

Use binary ephemeris files if possible. FreeFlyer allows for the ability to propagate a Spacecraft using a SPICE binary ephemeris. Their file size is smaller than its ASCII equivalent, and the read/write times are much faster

Tips for Scripting in FreeFlyer

Use Lists and Formation Objects

When you have multiple copies of the same type of object you can simplify your script by using Lists or Formations. Lists allow for group control of objects such as GroundStations, Vectors, output windows, report files, etc, and easily permits the use of For loops to configure the same type of objects rather than repeating similar blocks of code for each individual object. In addition to Lists, the Formation object is specifically for controlling one or more Spacecraft object and provides additional control over visualization and propagation using a single command or method.

Formation myFormation;

// Set the Formation Size
myFormation.Count = 3;

// Propagate the Entire Formation using the Step Method

Formation Objects

Figure 3: Constellation Modeling and Visualization

Import From a TLE

You can easily import a Formation of any size and initialize each Spacecraft with a single line of code using the Formation.LoadNoradTLE() method. The LoadNoradTLE() method will resize the Formation and populate its individual Spacecraft objects with all the states in a TLE file.

Formation myFormation;

Report myFormation.Count; // Returns a count of 0

myFormation.LoadNoradTLE(“GPS Fleet.tle”);

Report myFormation.Count; // Returns the count of TLE states loaded

Use Procedures

Be rigorous about writing modular code. If you ever find yourself writing the same portion of code more than once, then you are better off sticking that code in a Procedure instead. FreeFlyer Procedures provide the ability to execute generic sets of FreeFlyer script. Typically, you’ll want the Procedure to perform only one primary task, such as the configuration of similar objects. For example, if you have a large Formation of Spacecraft that requires attaching and configuring Tanks and Thrusters to model a specific engine, a Procedure would be ideal.

Define Procedure Tank_Thrusters_Configuration(Formation F);

Variable i;
List<Interpolated> interpolatedTank;
List<Thruster> chemThruster;

interpolatedTank.Count = F.Count;
chemThruster.Count = F.Count;

For i=0 to F.Count-1;
// Attach Tanks, Thrusters, and Valves
Attach interpolatedTank[i] to F[i];
Attach chemThruster[i] to F[i];
Attach interpolatedTank[i] to chemThruster[i];

// Configure Thruster
chemThruster[i].Type = “Chemical”;
chemThruster[i].ThrusterC1 = 444.8; // Thrust (N)
chemThruster[i].ThrusterK1 = 300; // Isp (sec)


Formation Formation1;
Formation1.Count = 500;

Call Tank_Thrusters_Configuration(Formation1);

Modularize Your MissionPlan Layout

The best approach for organizing and accounting for different portions of a Mission Plan is to separate out the tasks. You can differentiate multiple tasks by using separate FreeForms to execute specific code scripts. One example is having a FreeForm to generate maneuver planning options after executing a FreeForm that evaluates an upcoming conjunction and positively identifies a close approach. By separating tasks into multiple FreeForms, your code can be easily parsed by collaborators and the logical sequence of the MissionPlan is more defined.

Modularize Mission Plan

Figure 4: Mission Sequence of Separate Tasks

Use Structs

You should use Structs for organizing and sharing data when possible. Structs provide a simple way to define a collection of related FreeFlyer objects for easy code organization. Once a Struct is created users can conveniently pass data between processes and easily read/write JSON data.

Use Structs

Figure 5: Struct Example

As always, the FreeFlyer team is here to help! If you have questions on best practices and general FreeFlyer capabilities or just need some help getting your Mission Plan to run efficiently, reach out to us by phone or email. Stay tuned for more FreeFlyer Tips and Tricks!

> View FreeFlyer Blog