Skip to main content
Ctrl+K
PySTK - Home PySTK - Home
  • Getting started
  • User guide
  • API reference
  • Examples
  • Contribute
  • Artifacts
  • Release notes
Ctrl+K
  • GitHub
  • 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 v12.10.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 an online source, and propagate the satellite:

[9]:
propagator.common_tasks.add_segments_from_online_source("31698")
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.458394650 15 Mar 2024 06:33:14.874552309 665.4161576585711 N/A 92880 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 33W 521.7361574932914 7745.443597705119 33WWT2173645444 30R 419.93311379561754 3183.561712039982 30RVS1993383562
1 2 15 Mar 2024 07:58:01.500105812 15 Mar 2024 08:02:54.221900294 292.7217944814738 N/A 92881 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 29W 366.3935165120598 7345.475509726332 29WLP6639445476 27U 429.62145253038983 5346.728487058212 27UVP2962146728
2 3 15 Mar 2024 15:31:09.921082116 15 Mar 2024 15:41:19.040164169 609.1190820532502 N/A 92886 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 36S 488.9442601190258 3580.2257910631242 36SVA8894480226 33W 473.4377277545171 7750.483657208226 33WVT7343850484
3 4 15 Mar 2024 17:04:09.317277119 15 Mar 2024 17:15:35.046016598 685.7287394791856 N/A 92887 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 32R 684.1302660527213 2804.2680862111097 32RPP8413004268 29W 581.3720108624226 7521.636185530031 29WNR8137221636
4 5 15 Mar 2024 18:42:20.852340085 15 Mar 2024 18:47:07.001005909 286.14866582359537 N/A 92888 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 28S 411.79831536120537 4198.952095364672 28SDG1179898952 27U 413.58106896236995 6176.115365635918 27UVB1358176115
5 6 16 Mar 2024 04:31:32.112160260 16 Mar 2024 04:41:28.374312584 596.2621523233247 N/A 92894 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 37W 469.61327075042703 7158.601010664799 37WDM6961358601 34R 788.3165946467708 3051.857144479871 34RGR8831751857

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.458394650 0.0 0.0 10.0 1.704539 -155.457601 -129.369976 1.900768 15.042306 8.4 5.799513 8.809813 0.000048 0.0 0.0 0.0 0.0 0.0 None 290.0
1 15 Mar 2024 07:58:01.500105812 0.0 0.0 10.0 1.704517 -155.454205 -129.36658 1.900657 15.045591 8.4 5.802798 8.813098 0.000048 0.0 0.0 0.0 0.0 0.0 None 290.0
2 15 Mar 2024 15:31:09.921082116 0.0 0.0 10.0 1.704535 -155.391722 -129.304097 1.900751 15.108167 8.4 5.865375 8.875675 0.000043 0.0 0.0 0.0 0.0 0.0 None 290.0
3 15 Mar 2024 17:04:09.317277119 0.0 0.0 10.0 1.704539 -155.372865 -129.285241 1.900771 15.127045 8.4 5.884252 8.894552 0.000041 0.0 0.0 0.0 0.0 0.0 None 290.0
4 15 Mar 2024 18:42:20.852340085 0.0 0.0 10.0 1.704515 -155.405099 -129.317474 1.900647 15.094687 8.4 5.851894 8.862194 0.000044 0.0 0.0 0.0 0.0 0.0 None 290.0
5 16 Mar 2024 04:31:32.112160260 0.0 0.0 10.0 1.704533 -155.452536 -129.364911 1.90074 15.047343 8.4 5.80455 8.81485 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.765272 -128.677647 1.900766 15.734634 8.4 6.491841 9.502141 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.18293 -129.095305 1.900642 15.316851 8.4 6.074058 9.084358 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.772723 -128.685098 1.900746 15.727162 8.4 6.484369 9.494669 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.657114 -128.56949 1.90077 15.842795 8.4 6.600002 9.610302 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.759570010 0.0 0.0 10.0 1.704537 -152.945069 -126.857445 1.900759 17.554828 8.4 8.312036 11.322336 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
1 15 Mar 2024 15:33:36.548124287 0.0 0.0 10.0 1.704527 -152.052659 -125.965034 1.900709 18.447189 8.4 9.204396 12.214696 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
2 15 Mar 2024 17:07:34.413895835 0.0 0.0 10.0 1.704534 -148.927067 -122.839442 1.900741 21.572814 8.4 12.330021 15.340321 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
3 16 Mar 2024 04:32:28.173285490 0.0 0.0 10.0 1.704531 -154.328235 -128.24061 1.900728 16.171633 8.4 6.92884 9.93914 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.071471 -125.983846 1.900753 18.428421 8.4 9.185629 12.195928 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.374141 -125.286516 1.900692 19.125691 8.4 9.882898 12.893198 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.664614 -121.57699 1.900725 22.83525 8.4 13.592457 16.602757 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.707919 -127.620295 1.90072 16.791939 8.4 7.549146 10.559446 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.110464 -125.02284 1.900746 19.38942 8.4 10.146627 13.156927 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.737395 -124.64977 1.900671 19.762415 8.4 10.519622 13.529922 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.759570010 15 Mar 2024 06:30:05.292544675 377.53297466502795 N/A 92880 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 32V 542.9914547844054 7093.029825590829 32VNR4299193030 30T 693.268160537319 4503.764360442385 30TXL9326803764
1 2 15 Mar 2024 15:33:36.548124287 15 Mar 2024 15:39:49.757492637 373.2093683504718 N/A 92886 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 36T 281.6489596792608 4602.228375321448 36TTM8164902228 34W 432.3377418050118 7159.205100170075 34WDS3233859205
2 3 15 Mar 2024 17:07:34.413895835 15 Mar 2024 17:13:56.389724097 381.97582826247526 N/A 92887 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 32S 380.03813667867576 4231.048799749039 32SLH8003831049 30V 544.3636974596918 6859.598604629627 30VWP4436459599
3 4 16 Mar 2024 04:32:28.173285490 16 Mar 2024 04:38:33.018850881 364.84556539097684 N/A 92894 47.560500000000005 11.502699999999999 0.8701674116786334 47.560500000000005 ... 5270.488855657932 32TPT8826570489 36V 657.7641124914722 6783.648184475049 36VXN5776483648 35S 474.6037894108813 4268.177771106299 35SMC7460468178

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.759570010 0.23797 0.005026 10.0 1.704537 -153.188065 -127.10044 1.900759 17.311833 8.4 8.06904 11.07934 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
1 15 Mar 2024 15:33:36.548124287 0.174104 0.003672 10.0 1.704527 -152.230434 -126.14281 1.900709 18.269414 8.4 9.026621 12.036921 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
2 15 Mar 2024 17:07:34.413895835 0.085919 0.00175 10.0 1.704534 -149.014736 -122.927111 1.900741 21.485144 8.4 12.242352 15.252651 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
3 16 Mar 2024 04:32:28.173285490 0.479177 0.012249 10.0 1.704531 -154.81966 -128.732036 1.900728 15.680207 8.4 6.437414 9.447714 0.000014 0.0 0.0 0.0 0.0 0.0 None 290.0
4 15 Mar 2024 06:24:17.000000000 0.17687 0.003635 10.0 1.704536 -152.251976 -126.164351 1.900753 18.247917 8.4 9.005124 12.015424 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
5 15 Mar 2024 15:34:06.000000000 0.144554 0.002995 10.0 1.704524 -151.52169 -125.434065 1.900692 18.978142 8.4 9.735349 12.745649 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
6 15 Mar 2024 17:08:04.000000000 0.069449 0.001407 10.0 1.70453 -147.735471 -121.647846 1.900725 22.764393 8.4 13.5216 16.5319 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
7 16 Mar 2024 04:32:58.000000000 0.332202 0.007488 10.0 1.704529 -154.047609 -127.959985 1.90072 16.452249 8.4 7.209456 10.219756 0.000002 0.0 0.0 0.0 0.0 0.0 None 290.0
8 15 Mar 2024 06:24:47.000000000 0.136309 0.00276 10.0 1.704534 -151.249533 -125.161908 1.900746 19.250351 8.4 10.007559 13.017859 0.0 0.0 0.0 0.0 0.0 0.0 None 290.0
9 15 Mar 2024 15:34:36.000000000 0.124049 0.00254 10.0 1.70452 -150.863984 -124.77636 1.900671 19.635825 8.4 10.393032 13.403332 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.759570010 0.23797 0.005026 10.0 1.704537 -153.188065 -127.10044 7.279596 22.69067 8.4 13.447877 16.458177 0.0 6.108648 1.497981 0.000463 0.0 1.35 8.957091 84.045461
1 15 Mar 2024 15:33:36.548124287 0.174104 0.003672 10.0 1.704527 -152.230434 -126.14281 7.366124 23.734829 8.4 14.492036 17.502336 0.0 4.489744 1.458123 0.000346 0.0 1.35 7.298213 82.386583
2 15 Mar 2024 17:07:34.413895835 0.085919 0.00175 10.0 1.704534 -149.014736 -122.927111 7.489463 27.073866 8.4 17.831073 20.841373 0.0 2.228967 1.401542 0.011442 0.0 1.35 4.991951 80.08032
3 16 Mar 2024 04:32:28.173285490 0.479177 0.012249 10.0 1.704531 -154.81966 -128.732036 6.982775 20.762253 8.4 11.519461 14.529761 0.0 12.06549 1.710349 0.0 0.0 1.1256 14.90144 89.98981
4 15 Mar 2024 06:24:17.000000000 0.17687 0.003635 10.0 1.704536 -152.251976 -126.164351 7.362507 23.70967 8.4 14.466878 17.477178 0.0 4.560209 1.457031 0.000458 0.0 1.35 7.367698 82.456068
5 15 Mar 2024 15:34:06.000000000 0.144554 0.002995 10.0 1.704524 -151.52169 -125.434065 7.407127 24.484576 8.4 15.241783 18.252083 0.0 3.735207 1.438195 0.000325 0.0 1.35 6.523728 81.612097
6 15 Mar 2024 17:08:04.000000000 0.069449 0.001407 10.0 1.70453 -147.735471 -121.647846 7.513623 28.377291 8.4 19.134498 22.144798 0.0 1.803877 1.391453 0.002083 0.0 1.35 4.547414 79.635783
7 16 Mar 2024 04:32:58.000000000 0.332202 0.007488 10.0 1.704529 -154.047609 -127.959985 7.224173 21.775703 8.4 12.53291 15.54321 0.0 8.465337 1.570418 0.0 0.0 0.0 10.035755 85.124125
8 15 Mar 2024 06:24:47.000000000 0.136309 0.00276 10.0 1.704534 -151.249533 -125.161908 7.418791 24.768397 8.4 15.525604 18.535904 0.0 3.524091 1.431281 0.00045 0.0 1.35 6.305823 81.394192
9 15 Mar 2024 15:34:36.000000000 0.124049 0.00254 10.0 1.70452 -150.863984 -124.77636 7.435875 25.17103 8.4 15.928237 18.938537 0.0 3.209762 1.424816 0.000302 0.0 1.35 5.98488 81.073249

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
  • Show Source

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

Created using Sphinx 7.4.7.

Built with the Ansys Sphinx Theme 1.5.3.
Last updated on