All New Terrain Modeling in FreeFlyer®

November 15, 2019

Introducing the newest feature of FreeFlyer 7.5: Terrain! The Terrain object allows you to easily perform line-of-sight blockage analysis due to terrain features with no external terrain server required; the user provides the terrain data from any source with any resolution and support for all standard terrain data formats. Using the Terrain object, you can visualize terrain anywhere on Earth and compute visibility and viewshed combinations between any combination of assets in all analysis regimes.

Downloading Terrain Data

The first step to use the Terrain object in FreeFlyer is to download some terrain data. FreeFlyer can support most raster terrain file formats including, but not limited to: Global 30-Arc-Second Elevation (GTOPO30), Shuttle Radar Topography Mission (SRTM), and National Elevation Data (NED) data sets. These terrain data sets are arrays of regularly spaced elevation values referenced horizontally to a Universal Transverse Mercator (UTM) projection and are commonly referred to as Digital Elevation Models (DEM). FreeFlyer can process terrain data in any of the file formats listed on the Terrain Data Files page of the FreeFlyer Help File regardless of the origin of the data set. As an example, to download any of the file formats mentioned above, access USGS Earth Explorer and select your area of interest.

FreeFlyer Terrain Index Generator

Once you have downloaded the terrain data you’d like to analyze in FreeFlyer, you must create an index file to be used by the Terrain object. The FreeFlyer Terrain Index Generator, which is provided alongside the FreeFlyer executable in the FreeFlyer install directory, is a command-line utility that allows a user to pre-process Terrain data files and create corresponding terrain index files. The Terrain Index Generator creates binary terrain index files encoded with raster file data to allow FreeFlyer to evaluate line-of-sight intersections more efficiently. The Terrain Index Generator requires you to specify the vertical datum and height units used by the raster data to convert the data into the appropriate format.

To create a terrain index file, you will simply need to open a command prompt or terminal window, depending on your operating system, and navigate to the FreeFlyer install directory. Once in the install directory, call the Terrain Index Generator utility with the raster file terrain, vertical datum, height units, and data file path as shown below:

Figure 1: FreeFlyer Terrain Index Generator

Importing Terrain Data

Once, you’ve generated the index file(s) for the Terrain data you’d like to use, the next step is to import the data into FreeFlyer. Importing the Terrain data into FreeFlyer can be done easily either through the Terrain object GUI or through FreeFlyer Scripting.

To use the Terrain object GUI, first, right-click in your object browser and select the Terrain object. Once you’ve created your Terrain object, open the Terrain object GUI by double clicking on the Terrain object. With the Terrain object GUI open, you can specify the terrain raster data files to load by clicking the “Add Files” button as shown below:

Terrain Object GUI

Figure 2: Terrain object GUI

If you would prefer to use FreeFlyer Scripting, you can create a Terrain object and add files in just a few lines of code. The syntax is:

Terrain myTerrain;
myTerrain.AddFiles(".\TerrainFile.tif");

Using Terrain in FreeFlyer

Now that we have our Terrain loaded into FreeFlyer, let’s set up a simple contact analysis example between a GroundStation and a Spacecraft. In this example, we will place a GroundStation in our Terrain by specifying its longitude, latitude, and height based on Terrain, then create a VisibilitySegment between the Spacecraft and GroundStation to perform contact analysis. The first step is to place our GroundStation within the bounds of the Terrain file loaded in. Typically, the latitude and longitude bounds of a terrain data set are known to the user, but to determine whether a location is within the bounds of an unknown or new terrain data set you can use the Terrain.ContainsLocation() method which will return True/False for the inputted Latitude/Longitude location. Once you have determined a valid location, set your GroundStation’s latitude and longitude either in the GroundStation object GUI or by using FreeFlyer Scripting. With your GroundStation location set, set your GroundStation’s height using Terrain by using the GroundStation.SetHeight() method, as shown below:

GroundStation1.Latitude = 36;
GroundStation1.Longitude = 248;
GroundStation1.SetHeight(0.003,myTerrain);

Note, when using the GroundStation.SetHeight() with Terrain you must set the object’s height with respect to the provided terrain in kilometers, 0.003 is the default value (3 meters above the terrain surface). To validate that your GroundStation is properly using your Terrain data, you can report out the GroundStation’s height using the GroundStation.Height property.

Setting up a Visibility Segment

Now that you have set up both your Terrain and GroundStation objects, we will set up a simple VisibilitySegment to perform contact analysis between our Spacecraft and GroundStation objects. The only difference between setting up a VisibilitySegment with Terrain and without Terrain is defining your CelestialObjectOcculationModel. When using Terrain in a Visibility Segment the VisibilitySegment.CelestialObjectOcculationModel must always be set to 1 so that the Occultation Model being used for the Earth is an Ellipsoid. To set up your VisibilitySegment, use the syntax below:

// Set Up VisibiltySegments
VisibilitySegment VisSegWithTerrain;

VisSegWithTerrain.SetTarget(GroundStation1);
VisSegWithTerrain.SetObserver(Spacecraft1);
VisSegWithTerrain.AddOccultingBody(Earth);
VisSegWithTerrain.CelestialObjectOccultationModel = 1;
VisSegWithTerrain.AddOccultingTerrain(myTerrain);

The VisibilitySegment above sets the GroundStation as the target, the Spacecraft as the observer, and adds the Terrain data we’ve loaded in previously as an Occulting Terrain. Next, to visualize the impact of terrain on contact analysis, we will create a second VisibilitySegment that doesn’t use any occulting terrain, and two Vectors to see when we are in contact. Use the syntax below to create a second VisibilitySegment and identical Vectors built from the GroundStation to the Spacecraft:

VisibilitySegment VisSegWithoutTerrain;
VisSegWithoutTerrain.SetTarget(GroundStation1);
VisSegWithoutTerrain.SetObserver(Spacecraft1);
VisSegWithoutTerrain.AddOccultingBody(Earth);
VisSegWithoutTerrain.CelestialObjectOccultationModel = 1;

Vector VecWithTerrain;
Vector VecWithoutTerrain;
VecWithTerrain.BuildVector(9, GroundStation1, Spacecraft1);
VecWithTerrain.Color = ColorTools.Lime;

VecWithoutTerrain.BuildVector(9, GroundStation1, Spacecraft1);
VecWithoutTerrain.Color = ColorTools.Red;

Compare Visibility

To compare the Visibility between our two VisibilitySegments we will set up a simple While Loop and activate the Vectors we’ve created when Visibility is true. To do this, we propagate our Spacecraft for 2 days, check our VisibilitySegments contact using the instantaneous VisibilitySegment.Visibility() method, and update our Vectors in a ViewWindow to see what impact Terrain has on our Spacecraft’s contact. Using the syntax below, we will build our two ViewWindows, one that will be impacted by Terrain and one that will not, and activate our Vectors when the Visibility is true:

ViewWindow vwWithTerrain({Spacecraft1,GroundStation1,VecWithTerrain});
ViewWindow vwWithoutTerrain({Spacecraft1,GroundStation1,VecWithoutTerrain});

While (Spacecraft1.ElapsedTime < TimeSpan.FromDays(2));

// Check Visibility and Activate Vectors
If (VisSegWithTerrain.Visibility(Spacecraft1.Epoch) == 1);
VecWithTerrain.Active = 1;
Else;
VecWithTerrain.Active = 0;
End;

If (VisSegWithoutTerrain.Visibility(Spacecraft1.Epoch) == 1);
VecWithoutTerrain.Active = 1;
Else;
VecWithoutTerrain.Active = 0;
End;

// Update ViewWindows
Update vwWithTerrain;
Update vwWithoutTerrain;

Step Spacecraft1;

End;

Now that everything is set up, run your Mission Plan to visualize the results. Below is an example where the Terrain that we’ve input is blocking the Spacecraft from contacting the GroundStation. As you can see, in the left ViewWindow, the Vector is activated between the Spacecraft and GroundStation. In the right ViewWindow, although it is the same epoch, the Vector is inactive meaning there is no contact.

Figure 3: 3D View demonstrating the impact of Terrain during contact analysis

Visualizing Terrain in FreeFlyer

There are a handful of ways that you can visualize Terrain in FreeFlyer, including but not limited to: using a PointGroup or GraphicsOverlay. The most common approach to visualize Terrain in FreeFlyer is to use a PointGroup and set each point’s height to be associated with Terrain. Examples of this approach can be seen in the Drone Tracking GroundVehicle, Grand Canyon GroundVehicle Visibility, and Terrain Viewshed Analysis Sample Mission Plans, located in the Sample Mission Plans with New Features section of the FreeFlyer Home Screen. These Mission Plans use a Procedure that computes the number of points based on point spacing, sets the locations for a grid of points, and color the points in the PointGroup based on the height of Terrain using the ColorTools.InterpolateColorRGB() method. Below is an image taken from the Drone Tracking GroundVehicle Sample Mission Plan showing a PointGroup with the heights set using Terrain in both a 2D and 3D View:

Figure 4: 2D View visualizing the height of Terrain using a PointGroup

Figure 5: 3D View visualizing the height of Terrain using a PointGroup

> View FreeFlyer Blog