Skip to main content
Ctrl+K
PySTK - Home PySTK - Home
  • Home
  • Getting started
  • User guide
  • API reference
  • Examples
  • Contribute
  • Artifacts
    • Release notes
Ctrl+K
  • GitHub
  • Home
  • Getting started
  • User guide
  • API reference
  • Examples
  • Contribute
  • Artifacts
  • Release notes
Ctrl+K
  • GitHub

Section Navigation

Fundamental concepts

  • Create and load scenarios
  • Results and graphs

Basic examples

  • Create and load scenarios
  • Access between facility and satellite calculator
  • Results and graphs
  • Sensors and access

Coverage examples

  • Satellite coverage area calculator
  • Satellite coverage analysis

Orbital maneuvers

  • Hohmann transfer
  • Bi-elliptic transfer
  • Lambert transfer

Mission analysis

  • Porkchop plots

Communications and radar

  • Radar cross section detection calculator
  • Communication link budget calculator
  • Multifunction radar parametric study
  • Multifunction radar design

Aviator mission planning

  • Commercial aircraft fuel calculator with Aviator
  • Multi-aircraft carrier landing with Aviator
  • PyAnsys
  • Examples
  • Communication link budget calculator

Download as Python script

Download as Jupyter notebook

Download as PDF document


Communication link budget calculator#

This tutorial demonstrates how to model a communications system including transmitters and receivers, and calculate link budgets considering factors like terrain, rain models, and atmospheric losses using Python and PySTK. It is inspired by this tutorial.

What are communications links, and how are they evaluated?#

Communication links define the ways that a transmitter and a receiver access each other. STK allows the modeling of two kinds of links: basic and multi-hop. A basic communications link is access between just a single transmitter and a single receiver. A multi-hop communications link is defined by a group of communication objects consisting of a transmitter, receiver, re-transmitter, and another receiver. STK also allows setting constraints on communication links, including terrain masking constraints.

Communications links in STK can be analyzed using link budget reports, which include all the link parameters associated with the selected receiver or transmitter. Link budget reports take light speed delay into account. They also take computed refraction into account if enabled on the transmitter or receiver objects. Link budget reports include many communications-specific fields, including EIRP (effective isotropic radiated power in the link direction), C/N (Carrier-to-Noise ratio at the receiver input), Eb/No (Signal-to-Noise ratio at the receiver), and BER (Bit Error Rate). Link budget reports can also include access-specific information, such as the loss calculated by different selected models, including atmospheric, rain, cloud/fog, and terrain models.

Problem statement#

A team of scientists is monitoring glacial meltwater in a remote, mountainous location (latitude \(47.5605^\circ\), longitude \(11.5027^\circ\)). They need to determine how their location impacts a link budget between them and a low earth orbit (LEO), Earth observation satellite which is downloading data to the team. The satellite has a simple transmitter with an isotropic antenna pattern, a frequency of \(1.7045\) GHz, an EIRP of \(10\) dBW, a data rate of \(4.2\) Mb/sec, and a right-hand circular polarization. The camp’s receiver is steerable, points at the satellite, and is placed on a half power sensor located \(6\) ft above the ground, with a frequency of \(1.7045\) GHz and \(1.6\) m. The receiver has a parabolic antenna with a design frequency of \(1.7\) GHz, a \(1.6\) m diameter, and right-hand circular polarization.

Model and analyze a link budget between the ground site and the Earth observation satellite, taking into account different factors such as terrain, rain and atmospheric absorption, and system noise temperature from sun, atmosphere, rain, and cosmic background.

Launch a new STK instance#

Start by launching a new STK instance. In this example, STKEngine is used.

[1]:
from ansys.stk.core.stkengine import STKEngine


stk = STKEngine.start_application(no_graphics=False)
print(f"Using {stk.version}")
Using STK Engine v13.0.0

Create a new scenario#

Create a new scenario in STK by running:

[2]:
root = stk.new_object_root()
root.new_scenario("Communications")

Once the scenario is created, it is possible to show a 3D graphics window by running:

[3]:
from ansys.stk.core.stkengine.experimental.jupyterwidgets import GlobeWidget


globe = GlobeWidget(root, 640, 480)
globe.show()
[3]:
../_images/examples_communication-link-calculator_13_1.png

Set the scenario time period#

Using the newly created scenario, set the start and stop times. Rewind the scenario so that the graphics match the start and stop times of the scenario:

[4]:
scenario = root.current_scenario
scenario.set_time_period("15 Mar 2024 06:00:00.000", "16 Mar 2024 06:00:00.000")
root.rewind()

Add analytical and visual terrain#

Use an STK terrain file (file extension PDTT) included with the STK install to add analytical terrain to the scenario. The file contains information on the terrain around the scientists’ camp site. Use a Connect command to find the path to the RaistingStation.pdtt file:

[5]:
import pathlib

from ansys.stk.core.stkobjects import TerrainFileType


install_dir = root.execute_command("GetDirectory / STKHome")[0]
terrain_path = str(
    pathlib.Path(install_dir)
    / "Data"
    / "Resources"
    / "stktraining"
    / "imagery"
    / "RaistingStation.pdtt"
)

Then, add the file to the Earth central body’s terrain collection:

[6]:
terrain = scenario.terrain.item("Earth").terrain_collection.add(
    terrain_path, TerrainFileType.PDTT
)

This file is used for analysis by default after it is inserted.

Add a satellite#

The Earth observation satellite is in a sun-synchronous orbit. It can thus be modelled by an SGP4 propagator, which is used for LEO satellites. The satellite communicating with the camp has a common name of TerraSarX, which corresponds to a space surveillance catalog number of \(31698\).

To add the satellite, first insert a satellite object:

[7]:
from ansys.stk.core.stkobjects import PropagatorType, STKObjectType


satellite = root.current_scenario.children.new(
    STKObjectType.SATELLITE, "TerraSarX_31698"
)

Then, set the satellite’s propagator to the SGP4 propagator:

[8]:
satellite.set_propagator_type(PropagatorType.SGP4)
propagator = satellite.propagator

Finally, use the propagator’s common_tasks property to add the satellite’s orbit from a local file, and propagate the satellite:

[9]:
tle_file = pathlib.Path("data") / "TerraSarX_31698.tle"
propagator.common_tasks.add_segments_from_file("31698", str(tle_file.resolve()))
propagator.propagate()

Add the camp site#

Add a place object to represent the camp site:

[10]:
camp_site = root.current_scenario.children.new(STKObjectType.PLACE, "CampSite")

Assign the site’s position to latitude \(47.5605^\circ\) and longitude \(11.5027^\circ\), with an elevation of \(6\) ft (\(0.0018288\) km) to simulate the height of the equipment at the site:

[11]:
camp_site.position.assign_planetodetic(47.5605, 11.5027, 0.0018288)

Model a simple transmitter#

The satellite has a simple transmitter model, a model type which uses an isotropic, omnidirectional antenna, which is an ideal spherical pattern antenna with constant gain. Insert the transmitter on the satellite:

[12]:
transmitter = satellite.children.new(STKObjectType.TRANSMITTER, "DownloadTransmitter")

The transmitter’s model property now contains a TransmitterModelSimple object. Set the model’s frequency to \(1.7045\) GHz:

[13]:
from ansys.stk.core.stkobjects import TransmitterModelSimple
[14]:
transmitter_model = TransmitterModelSimple(
    transmitter.model_component_linking.component
)
transmitter_model.frequency = 1.7045

Then, set the model’s EIRP, which is the effective isotropic radiated power at the output of the transmit antenna. Set the EIRP to \(10\) dBW:

[15]:
transmitter_model.eirp = 10

Next, set the model’s data rate to \(4.2\) Mb/sec:

[16]:
transmitter_model.data_rate = 4.2

Then, enable polarization on the model:

[17]:
transmitter_model.enable_polarization = True

Finally, set the model’s polarization type to right-hand circular:

[18]:
from ansys.stk.core.stkobjects import PolarizationType


transmitter_model.set_polarization_type(PolarizationType.RIGHT_HAND_CIRCULAR)

Add a steerable sensor#

The receiver antenna at the camp site is steerable. To create a steering device, add a sensor object:

[19]:
sensor = camp_site.children.new(STKObjectType.SENSOR, "ServoMotor")

Then, set the sensor’s pattern to a half power pattern, which is designed to visually model parabolic antennas. The sensor half angle is determined by frequency and antenna diameter.

[20]:
from ansys.stk.core.stkobjects import SensorPattern


sensor.set_pattern_type(SensorPattern.HALF_POWER)

The sensor’s pattern property now holds a SensorHalfPowerPattern object, through which it is possible to configure the half power model. First, set the sensor’s frequency to \(1.7045\) GHz:

[21]:
sensor.pattern.frequency = 1.7045

Then, set the sensor’s antenna diameter to \(1.6\) m:

[22]:
sensor.pattern.antenna_diameter = 1.6

The sensor is steerable and tracks the satellite, so set the sensor’s pointing type to targeted:

[23]:
from ansys.stk.core.stkobjects import SensorPointing


sensor.set_pointing_type(SensorPointing.TARGETED)

The sensor’s pointing property now holds a SensorPointingTargeted object, through which it is possible to set the satellite as the sensor’s target:

[24]:
sensor.pointing.targets.add("Satellite/TerraSarX_31698")

Calculate access#

Get and compute the access between the camp site’s sensor and the satellite:

[25]:
sensor_to_satellite_access = sensor.get_access_to_object(satellite)
sensor_to_satellite_access.compute_access()

Then, get the access data during the entire scenario as a dataframe:

[26]:
sensor_to_satellite_access_df = (
    sensor_to_satellite_access.data_providers.item("Access Data")
    .execute(scenario.start_time, scenario.stop_time)
    .data_sets.to_pandas_dataframe()
)
sensor_to_satellite_access_df
[26]:
access number start time stop time duration from pass number to pass number from start lat from start lon from start alt from stop lat ... from stop utm northing from stop mgrs cell to start utm zone to start utm easting to start utm northing to start mgrs cell to stop utm zone to stop utm easting to stop utm northing to stop mgrs cell
0 1 15 Mar 2024 06:22:09.443314849 15 Mar 2024 06:33:14.866755949 665.4234411005375 N/A 92880 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 33W 521.7954487315626 7745.457422478889 33WWT2179545457 30R 419.9698962754109 3183.534462311691 30RVS1997083534
1 2 15 Mar 2024 07:58:01.509897765 15 Mar 2024 08:02:54.261366325 292.7514685598135 N/A 92881 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 29W 366.4811538707948 7345.5723083756475 29WLP6648145572 27U 429.635540505229 5346.632570111936 27UVP2963646633
2 3 15 Mar 2024 15:31:09.903349497 15 Mar 2024 15:41:19.036706331 609.1333568343689 N/A 92886 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 36S 488.966908755242 3580.178348010544 36SVA8896780178 33W 473.4374926246157 7750.5169347225765 33WVT7343750517
3 4 15 Mar 2024 17:04:09.311421908 15 Mar 2024 17:15:35.054467566 685.7430456574948 N/A 92887 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 32R 684.1474501848286 2804.220988276392 32RPP8414704221 29W 581.3694855552546 7521.669227805509 29WNR8136921669
4 5 15 Mar 2024 18:42:20.848340863 15 Mar 2024 18:47:07.026427127 286.1780862634332 N/A 92888 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 28S 411.8249747027645 4198.847377963612 28SDG1182598847 27U 413.56542396974925 6176.20794155235 27UVB1356576208
5 6 16 Mar 2024 04:31:32.114385058 16 Mar 2024 04:41:28.358636559 596.2442515003349 N/A 92894 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 37W 469.59105863692537 7158.56425396052 37WDM6959158564 34R 788.3272323313072 3051.9192850573518 34RGR8832751919

6 rows × 60 columns

The sensor is able to access the satellite six times throughout the duration of the scenario.

The access between the sensor and the satellite can be seen in the 3D graphics window approximately \(1389\) seconds after the scenario begins:

[27]:
root.current_time = 1389.458394
globe.camera.position = [2703.568833967754, -5862.711497073381, 9424.82507431983]
globe.show()
[27]:
../_images/examples_communication-link-calculator_70_0.png

Model the receiver#

The sensor’s receiver is modelled using a complex receiver model, which allows selecting among a variety of analytical and realistic antenna models and defining the characteristics of the selected antenna type.

First, add the receiver on the sensor:

[28]:
receiver = sensor.children.new(STKObjectType.RECEIVER, "DownloadReceiver")

Then, set the receiver’s model type to the complex receiver model:

[29]:
receiver.model_component_linking.set_component("Complex Receiver Model")

Next, use the model’s antenna_control property to set the receiver’s embedded model to a parabolic antenna:

[30]:
from ansys.stk.core.stkobjects import ReceiverModelComplex
[31]:
receiver_model = ReceiverModelComplex(receiver.model_component_linking.component)
receiver_model.antenna_control.embedded_model_component_linking.set_component(
    "Parabolic"
)

The receiver model’s antenna control’s embedded_model property now holds an AntennaModelParabolic object, through which it is possible to configure the antenna model. First, configure the antenna model to use diameter as its input type:

[32]:
from ansys.stk.core.stkobjects import AntennaModelInputType, AntennaModelParabolic


antenna_control = AntennaModelParabolic(
    receiver_model.antenna_control.embedded_model_component_linking.component
)
antenna_control.input_type = AntennaModelInputType.DIAMETER

Then, set the diameter to \(1.6\) m:

[33]:
antenna_control.diameter = 1.6

Set the design frequency to \(1.7\) GHz:

[34]:
antenna_control.design_frequency = 1.7

Next, enable the use of polarization on the receiver model:

[35]:
receiver_model.enable_polarization = True

The receiver’s polarization type is the same as the transmitter’s polarization, so set the model’s polarization type to right-hand circular:

[36]:
receiver_model.set_polarization_type(PolarizationType.RIGHT_HAND_CIRCULAR)

Calculate access#

Get and calculate the access between the receiver and transmitter:

[37]:
receiver_basic_access = receiver.get_access_to_object(transmitter)
receiver_basic_access.compute_access()

Then, get the link information for the access for the entire scenario, using a time step of \(30\) s:

[38]:
receiver_basic_link_df = (
    receiver_basic_access.data_providers.item("Link Information")
    .execute(scenario.start_time, scenario.stop_time, 30)
    .data_sets.to_pandas_dataframe()
)

Get the columns corresponding to time, atmospheric loss (atmos loss), rain loss, EIRP in the link direction (eirp), received isotropic power at the receiver antenna (rcvd. iso. power), power flux density at the receiver antenna (flux density), receiver gain over equivalent noise temperature (g/T), carrier-to-noise density at the receiver input (c/no), bandwidth, carrier-to-noise ratio at the receiver input (c/n), signal-to-noise ratio at the receiver (eb/no), bit error rate (ber), and calculated system noise temperatures (tatmos, train, tsun, tearth, tcosmic, tantenna, tequivalent):

[39]:
link_budget_columns = [
    "time",
    "atmos loss",
    "rain loss",
    "eirp",
    "rcvd. frequency",
    "rcvd. iso. power",
    "flux density",
    "g/t",
    "c/no",
    "bandwidth",
    "c/n",
    "eb/no",
    "ber",
    "tatmos",
    "train",
    "tsun",
    "tearth",
    "tcosmic",
    "tantenna",
    "tequivalent",
]
receiver_basic_link_df.head(10)[link_budget_columns]
[39]:
time atmos loss rain loss eirp rcvd. frequency rcvd. iso. power flux density g/t c/no bandwidth c/n eb/no ber tatmos train tsun tearth tcosmic tantenna tequivalent
0 15 Mar 2024 06:22:09.443314849 0.0 0.0 10.0 1.704539 -155.457681 -129.370056 1.900768 15.042226 8.4 5.799433 8.809733 0.000048 0.0 0.0 0.0 0.0 0.0 None 290.0
1 15 Mar 2024 07:58:01.509897765 0.0 0.0 10.0 1.704517 -155.454253 -129.366629 1.900657 15.045542 8.4 5.802749 8.813049 0.000048 0.0 0.0 0.0 0.0 0.0 None 290.0
2 15 Mar 2024 15:31:09.903349497 0.0 0.0 10.0 1.704535 -155.39192 -129.304295 1.900751 15.10797 8.4 5.865177 8.875477 0.000043 0.0 0.0 0.0 0.0 0.0 None 290.0
3 15 Mar 2024 17:04:09.311421908 0.0 0.0 10.0 1.704539 -155.373049 -129.285424 1.900771 15.126861 8.4 5.884069 8.894368 0.000041 0.0 0.0 0.0 0.0 0.0 None 290.0
4 15 Mar 2024 18:42:20.848340863 0.0 0.0 10.0 1.704515 -155.405239 -129.317615 1.900647 15.094547 8.4 5.851754 8.862054 0.000044 0.0 0.0 0.0 0.0 0.0 None 290.0
5 16 Mar 2024 04:31:32.114385058 0.0 0.0 10.0 1.704533 -155.452383 -129.364758 1.90074 15.047496 8.4 5.804703 8.815003 0.000048 0.0 0.0 0.0 0.0 0.0 None 290.0
6 15 Mar 2024 06:22:39.000000000 0.0 0.0 10.0 1.704539 -154.764986 -128.677361 1.900766 15.734919 8.4 6.492126 9.502426 0.000012 0.0 0.0 0.0 0.0 0.0 None 290.0
7 15 Mar 2024 07:58:31.000000000 0.0 0.0 10.0 1.704514 -155.183028 -129.095403 1.900642 15.316753 8.4 6.07396 9.08426 0.000029 0.0 0.0 0.0 0.0 0.0 None 290.0
8 15 Mar 2024 15:31:39.000000000 0.0 0.0 10.0 1.704535 -154.77255 -128.684925 1.900746 15.727335 8.4 6.484542 9.494842 0.000012 0.0 0.0 0.0 0.0 0.0 None 290.0
9 15 Mar 2024 17:04:39.000000000 0.0 0.0 10.0 1.704539 -154.657169 -128.569544 1.90077 15.84274 8.4 6.599947 9.610247 0.00001 0.0 0.0 0.0 0.0 0.0 None 290.0

The dataframe now shows information corresponding to an STK link budget report. From the data, it is possible to see that as the satellite rises over the horizon of the central body, the site receives transmissions. When the satellite falls below the horizon, the site loses transmissions. Additionally, because the access calculation does not include any environmental factor models or system noise temperature considerations, the columns corresponding to the losses/noise all have values of 0.

Add terrain to the analysis#

Next, add a terrain mask to the receiver to add terrain into the access analysis. A terrain mask causes STK to constrain access to an object by any terrain data in the line of sight to which access is being calculated. Add a terrain mask access constraint:

[40]:
from ansys.stk.core.stkobjects import AccessConstraintType


terrain_constraint = receiver.access_constraints.add_constraint(
    AccessConstraintType.TERRAIN_MASK
)

Recalculate the access between the receiver and transmitter, then get the data corresponding to a link budget report:

[41]:
receiver_basic_access.compute_access()
receiver_terrain_link_df = (
    receiver_basic_access.data_providers.item("Link Information")
    .execute(scenario.start_time, scenario.stop_time, 30)
    .data_sets.to_pandas_dataframe()
)
receiver_terrain_link_df.head(10)[link_budget_columns]
[41]:
time atmos loss rain loss eirp rcvd. frequency rcvd. iso. power flux density g/t c/no bandwidth c/n eb/no ber tatmos train tsun tearth tcosmic tantenna tequivalent
0 15 Mar 2024 06:23:47.738225524 0.0 0.0 10.0 1.704537 -152.945325 -126.8577 1.900759 17.554573 8.4 8.31178 11.32208 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
1 15 Mar 2024 15:33:36.530887310 0.0 0.0 10.0 1.704527 -152.052921 -125.965297 1.900709 18.446927 8.4 9.204134 12.214434 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
2 15 Mar 2024 17:07:34.407551564 0.0 0.0 10.0 1.704534 -148.92746 -122.839835 1.900741 21.572421 8.4 12.329628 15.339928 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
3 16 Mar 2024 04:32:28.173790081 0.0 0.0 10.0 1.704531 -154.328097 -128.240473 1.900728 16.17177 8.4 6.928977 9.939277 0.000004 0.0 0.0 0.0 0.0 0.0 None 290.0
4 15 Mar 2024 06:24:17.000000000 0.0 0.0 10.0 1.704536 -152.071071 -125.983447 1.900753 18.428821 8.4 9.186028 12.196328 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
5 15 Mar 2024 15:34:06.000000000 0.0 0.0 10.0 1.704524 -151.374025 -125.2864 1.900692 19.125806 8.4 9.883014 12.893314 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
6 15 Mar 2024 17:08:04.000000000 0.0 0.0 10.0 1.70453 -147.664761 -121.577136 1.900725 22.835103 8.4 13.59231 16.60261 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
7 16 Mar 2024 04:32:58.000000000 0.0 0.0 10.0 1.704529 -153.707783 -127.620159 1.90072 16.792075 8.4 7.549283 10.559583 0.000001 0.0 0.0 0.0 0.0 0.0 None 290.0
8 15 Mar 2024 06:24:47.000000000 0.0 0.0 10.0 1.704534 -151.110018 -125.022393 1.900746 19.389866 8.4 10.147074 13.157374 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
9 15 Mar 2024 15:34:36.000000000 0.0 0.0 10.0 1.70452 -150.737319 -124.649695 1.900671 19.76249 8.4 10.519697 13.529997 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0

Next, get the access data for the updated access:

[42]:
receiver_basic_access.data_providers.item("Access Data").execute(
    scenario.start_time, scenario.stop_time
).data_sets.to_pandas_dataframe()
[42]:
access number start time stop time duration from pass number to pass number from start lat from start lon from start alt from stop lat ... from stop utm northing from stop mgrs cell to start utm zone to start utm easting to start utm northing to start mgrs cell to stop utm zone to stop utm easting to stop utm northing to stop mgrs cell
0 1 15 Mar 2024 06:23:47.738225524 15 Mar 2024 06:30:05.282824306 377.54459878182047 N/A 92880 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 32V 543.0636494766094 7093.091092135564 32VNR4306493091 30T 693.313092566523 4503.7520342763055 30TXL9331303752
1 2 15 Mar 2024 15:33:36.530887310 15 Mar 2024 15:39:49.753884808 373.22299749790545 N/A 92886 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 36T 281.67166599554895 4602.178604418606 36TTM8167202179 34W 432.3401785798321 7159.2394394649245 34WDS3234059239
2 3 15 Mar 2024 17:07:34.407551564 15 Mar 2024 17:13:56.396616040 381.989064475958 N/A 92887 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 32S 380.05827134699314 4230.991097930746 32SLH8005830991 30V 544.3663807790708 6859.623176130229 30VWP4436659623
3 4 16 Mar 2024 04:32:28.173790081 16 Mar 2024 04:38:33.006192609 364.8324025285692 N/A 92894 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 36V 657.7482993685447 6783.619600446967 36VXN5774883620 35S 474.6110975590674 4268.22597398794 35SMC7461168226

4 rows × 60 columns

Before adding a terrain mask, there were \(6\) accesses between the receiver and transmitter. By adding a terrain mask, the accesses blocked by terrain have been removed from the report, and there are now only \(4\) accesses between the receiver and transmitter.

Model environmental factors#

Environmental factors can affect the performance of a communications link. In STK, it is possible to enable or disable the use of different environmental factors at three levels: scenario, platform (facilities, places, targets, and all vehicles except satellites), and subobject (transmitter, receiver, radar, and antenna). In this case, since the scenario only includes a single receiver/transmitter pair, set the environmental factors at the scenario level.

First, add a rain model, which is used to estimate the amount of degradation (or fading) of signal when passing through rain. The degradation is primarily due to absorption by water molecules and is a function of frequency and elevation angle. Generally speaking, the rain loss increases with increasing frequency. The loss also increases with decreasing ground elevation angle due to a greater path distance through the portion of the atmosphere where rain occurs. Rain also causes an increase in the antenna noise temperature. Set the enable_rain_loss property to True on the scenario’s RF environment’s propagation channel:

[43]:
scenario.rf_environment.propagation_channel.enable_rain_loss = True

Then, enable the use of the atmospheric absorption model:

[44]:
scenario.rf_environment.propagation_channel.enable_atmospheric_absorption = True

It is possible to configure which specific model is used for the different environmental factors. However, in this case, the default models are sufficient.

Next, recalculate the access between the receiver and transmitter:

[45]:
receiver_basic_access.compute_access()
receiver_environmental_link_df = (
    receiver_basic_access.data_providers.item("Link Information")
    .execute(scenario.start_time, scenario.stop_time, 30)
    .data_sets.to_pandas_dataframe()
)
receiver_environmental_link_df.head(10)[link_budget_columns]
[45]:
time atmos loss rain loss eirp rcvd. frequency rcvd. iso. power flux density g/t c/no bandwidth c/n eb/no ber tatmos train tsun tearth tcosmic tantenna tequivalent
0 15 Mar 2024 06:23:47.738225524 0.237986 0.005026 10.0 1.704537 -153.188337 -127.100712 1.900759 17.311561 8.4 8.068768 11.079068 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
1 15 Mar 2024 15:33:36.530887310 0.174104 0.003672 10.0 1.704527 -152.230698 -126.143073 1.900709 18.26915 8.4 9.026358 12.036658 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
2 15 Mar 2024 17:07:34.407551564 0.085921 0.00175 10.0 1.704534 -149.015131 -122.927506 1.900741 21.48475 8.4 12.241957 15.252257 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
3 16 Mar 2024 04:32:28.173790081 0.479191 0.012249 10.0 1.704531 -154.819537 -128.731913 1.900728 15.68033 8.4 6.437537 9.447837 0.000014 0.0 0.0 0.0 0.0 0.0 None 290.0
4 15 Mar 2024 06:24:17.000000000 0.176844 0.003634 10.0 1.704536 -152.25155 -126.163925 1.900753 18.248343 8.4 9.00555 12.01585 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
5 15 Mar 2024 15:34:06.000000000 0.14454 0.002994 10.0 1.704524 -151.52156 -125.433935 1.900692 18.978272 8.4 9.735479 12.745779 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
6 15 Mar 2024 17:08:04.000000000 0.069448 0.001407 10.0 1.70453 -147.735616 -121.647992 1.900725 22.764248 8.4 13.521455 16.531755 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
7 16 Mar 2024 04:32:58.000000000 0.332212 0.007489 10.0 1.704529 -154.047483 -127.959859 1.90072 16.452375 8.4 7.209582 10.219882 0.000002 0.0 0.0 0.0 0.0 0.0 None 290.0
8 15 Mar 2024 06:24:47.000000000 0.136291 0.002759 10.0 1.704534 -151.249069 -125.161444 1.900746 19.250816 8.4 10.008023 13.018323 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
9 15 Mar 2024 15:34:36.000000000 0.12404 0.00254 10.0 1.70452 -150.863899 -124.776274 1.900671 19.635911 8.4 10.393118 13.403418 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0

After adding environmental factor models, the atmospheric and rain losses are now greater than \(0\). However, the losses are minimal, so the losses in C/N and Eb/No are also minimal.

Model system noise temperature#

The receiver’s system noise temperature enables specifying the system’s inherent noise characteristics, which can help simulate real-world RF situations more accurately. STK can use either a constant system noise temperature value, or can calculate it based off of different noise sources. In this case, configure the receiver model’s system noise temperature to use calculated values:

[46]:
from ansys.stk.core.stkobjects import NoiseTemperatureComputeType


receiver_model.system_noise_temperature.compute_type = (
    NoiseTemperatureComputeType.CALCULATE
)

Do the same for the model’s antenna noise temperature:

[47]:
receiver_model.system_noise_temperature.antenna_noise_temperature.compute_type = (
    NoiseTemperatureComputeType.CALCULATE
)

Then, enable the use of sun, atmosphere, rain, and cosmic background in computations:

[48]:
receiver_model.system_noise_temperature.antenna_noise_temperature.use_sun = True
receiver_model.system_noise_temperature.antenna_noise_temperature.use_atmosphere = True
receiver_model.system_noise_temperature.antenna_noise_temperature.use_rain = True
receiver_model.system_noise_temperature.antenna_noise_temperature.use_cosmic_background = True

Finally, recompute the access and get the updated link information:

[49]:
receiver_basic_access.compute_access()
receiver_noise_link_df = (
    receiver_basic_access.data_providers.item("Link Information")
    .execute(scenario.start_time, scenario.stop_time, 30)
    .data_sets.to_pandas_dataframe()
)
receiver_noise_link_df.head(10)[link_budget_columns]
[49]:
time atmos loss rain loss eirp rcvd. frequency rcvd. iso. power flux density g/t c/no bandwidth c/n eb/no ber tatmos train tsun tearth tcosmic tantenna tequivalent
0 15 Mar 2024 06:23:47.738225524 0.237986 0.005026 10.0 1.704537 -153.188337 -127.100712 7.279575 22.690377 8.4 13.447584 16.457884 0.0 6.109048 1.497992 0.000463 0.0 1.35 8.957503 84.045872
1 15 Mar 2024 15:33:36.530887310 0.174104 0.003672 10.0 1.704527 -152.230698 -126.143073 7.366123 23.734565 8.4 14.491772 17.502072 0.0 4.489758 1.458123 0.000346 0.0 1.35 7.298228 82.386597
2 15 Mar 2024 17:07:34.407551564 0.085921 0.00175 10.0 1.704534 -149.015131 -122.927506 7.48946 27.073468 8.4 17.830676 20.840976 0.0 2.229015 1.401544 0.01145 0.0 1.35 4.992009 80.080378
3 16 Mar 2024 04:32:28.173790081 0.479191 0.012249 10.0 1.704531 -154.819537 -128.731913 6.982759 20.76236 8.4 11.519567 14.529867 0.0 12.065826 1.710365 0.0 0.0 1.125587 14.901778 89.990147
4 15 Mar 2024 06:24:17.000000000 0.176844 0.003634 10.0 1.704536 -152.25155 -126.163925 7.362543 23.710132 8.4 14.467339 17.477639 0.0 4.559556 1.457015 0.000458 0.0 1.35 7.367028 82.455397
5 15 Mar 2024 15:34:06.000000000 0.14454 0.002994 10.0 1.704524 -151.52156 -125.433935 7.407146 24.484726 8.4 15.241933 18.252233 0.0 3.734853 1.438186 0.000325 0.0 1.35 6.523364 81.611734
6 15 Mar 2024 17:08:04.000000000 0.069448 0.001407 10.0 1.70453 -147.735616 -121.647992 7.513625 28.377148 8.4 19.134355 22.144655 0.0 1.80384 1.391452 0.002079 0.0 1.35 4.547372 79.635741
7 16 Mar 2024 04:32:58.000000000 0.332212 0.007489 10.0 1.704529 -154.047483 -127.959859 7.22416 21.775816 8.4 12.533023 15.543323 0.0 8.465584 1.570427 0.0 0.0 0.0 10.03601 85.12438
8 15 Mar 2024 06:24:47.000000000 0.136291 0.002759 10.0 1.704534 -151.249069 -125.161444 7.418816 24.768886 8.4 15.526093 18.536393 0.0 3.523639 1.43127 0.00045 0.0 1.35 6.305359 81.393729
9 15 Mar 2024 15:34:36.000000000 0.12404 0.00254 10.0 1.70452 -150.863899 -124.776274 7.435889 25.171128 8.4 15.928335 18.938635 0.0 3.209515 1.42481 0.000302 0.0 1.35 5.984627 81.072997

There are now non-zero values in the tatmos, train, tsun, tcosmic, tantenna, and tequivalent columns. Calculating system noise temperature improved the report and extended the time available for downloading data.

Plot the different link budgets#

Visualize the calculated link budgets under the different modeling factors:

[50]:
import matplotlib.dates as md
import matplotlib.pyplot as plt
import pandas as pd


# Create plot
fig, ax = plt.subplots()

# Format data
receiver_environmental_link_df["time"] = pd.to_datetime(
    receiver_environmental_link_df["time"]
)
receiver_environmental_link_df.sort_values(by="time", inplace=True)
receiver_terrain_link_df["time"] = pd.to_datetime(receiver_terrain_link_df["time"])
receiver_terrain_link_df.sort_values(by="time", inplace=True)
receiver_noise_link_df["time"] = pd.to_datetime(receiver_noise_link_df["time"])
receiver_noise_link_df.sort_values(by="time", inplace=True)

# Plot dataframes
receiver_environmental_link_df.plot(
    x="time", y="c/no", ax=ax, label="terrain, environmental", color="darkblue"
)
receiver_terrain_link_df.plot(
    x="time", y="c/no", ax=ax, label="terrain", color="deeppink"
)
receiver_noise_link_df.plot(
    x="time",
    y="c/no",
    ax=ax,
    label="terrain, environmental, system noise",
    color="palegreen",
)

# Configure plot style
ax.set_facecolor("whitesmoke")
ax.grid(visible=True, which="both")

# Set title and labels
ax.set_title("Carrier to Noise Ratio Over Time Under Different Models")
ax.set_xlabel("Time")
ax.set_ylabel("C/N (dB)")

# Improve x-axis formatting
formatter = md.DateFormatter("%H:%M:%S")
ax.xaxis.set_major_formatter(formatter)

# Set figure size
fig.set_size_inches(15, 8)

# Show figure
plt.show()
../_images/examples_communication-link-calculator_128_0.png

The model accounting for only terrain has similar C/N values to the model accounting for terrain and environmental factors, as the losses from environmental factors were minimal in this analysis. The model accounting for terrain, environmental factors, and system noise consistently had the highest C/N values, as calculating system noise temperature improved the link budget.

previous

Radar cross section detection calculator

next

Multifunction radar parametric study

On this page
  • What are communications links, and how are they evaluated?
  • Problem statement
  • Launch a new STK instance
  • Create a new scenario
  • Set the scenario time period
  • Add analytical and visual terrain
  • Add a satellite
  • Add the camp site
  • Model a simple transmitter
  • Add a steerable sensor
  • Calculate access
  • Model the receiver
  • Calculate access
  • Add terrain to the analysis
  • Model environmental factors
  • Model system noise temperature
  • Plot the different link budgets
Edit on GitHub

© Copyright (c) 2025 ANSYS, Inc. All rights reserved.

Created using Sphinx 7.4.7.

Built with the Ansys Sphinx Theme 1.6.3.
Last updated on