Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: link budgets #7

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 175 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,180 @@
//----------------------------------------------------------------------------------------
// MacOS
// Editor
//----------------------------------------------------------------------------------------
**/*.DS_Store
.vscode

//----------------------------------------------------------------------------------------
// Outpu
// Output
//----------------------------------------------------------------------------------------
**/output/
**/output/

//----------------------------------------------------------------------------------------
// Python
//----------------------------------------------------------------------------------------

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "analysis/modules/pylink"]
path = analysis/modules/pylink
url = [email protected]:stanford-ssi/pylink.git
1 change: 1 addition & 0 deletions analysis/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.conda.env
5 changes: 5 additions & 0 deletions analysis/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Analysis

## Environment Setup

First, use the `environment.yml` file to set up your python environment. Any version of Python roughly 3.6 or later should be fine, but we didn't test that rigourosly (we are currently using 3.9 and will upgrade to 3.10 when it comes out). Next, install all the submodules in `modules/` into your python environment (they are modified versions of pypi packages).
22 changes: 20 additions & 2 deletions analysis/comms/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,20 @@
# Comms
pylink-satcom
# Link Budgets

## Rough Plan of Attack

Run antenna simulations in `4nec2`, and then use pylink-satcom
to simulate the RF links, and then use Python to simulate the
data encoding and generate plots of SNR vs Error rate. In
addition, use Python to generate graphs of link margin over
the course of a couple of ground pass profiles, and generate
statistics of data per ground pass, average number of ground
passes per day, and data throughput.

<https://arxiv.org/pdf/1905.11252.pdf>

## Current Needs

- Figure out RX and TX efficiencies and es/n0 (not SNR) for both LoRa
and frequency hopping.

- Read more about radios and determine components with greater accuracy
43 changes: 43 additions & 0 deletions analysis/comms/modulation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env python

import os

import pylink
from sband import DOWNLINK

"""Example of using a complex modulation with many code options.
Complex modulations, such as DVB-S2(X) have many different code-rate
options available for variable/adaptive bitrates, or encoder/decoder
capabilities, etc. The ability to specify multiple code options and
select the appropriate option for the circumstances (largely dependent
upon the allocation size and the received C/N0) is included.
"""

m = DOWNLINK
e = m.enum

# Modify our boilerplate model to illustrate the coding
m.override(e.allocation_hz, 5e6)
m.override(e.cn0_db, 73)
m.override(e.target_margin_db, 1)
m.override(e.implementation_loss_db, 1)

# Observe the best code option
code = m.best_modulation_code
print("=== Modulation: %s ===" % m.modulation_name)
print(" Code: %s" % code.name)
print(" Transmit Spectral Efficiency: %f" % code.tx_eff)
print(" Receive Spectral Efficiency: %f" % code.rx_eff)
print(" Required Es/N0: %f" % code.esn0_db)
print(" Required Eb/N0: %f" % code.ebn0_db)

print("")
print("=== System ===")
print(" Transmit Spectral Efficiency: %f" % m.tx_spectral_efficiency_bps_per_hz)
print(" Receive Spectral Efficiency: %f" % m.rx_spectral_efficiency_bps_per_hz)
print(" Required Demod Eb/N0: %f" % m.required_demod_ebn0_db)
print(" Implementation Losses: %f" % m.implementation_loss_db)
print(" Required Eb/N0: %f" % m.required_ebn0_db)

print("")
print("Note how the transmit and receive spectral efficiencies are different.")
113 changes: 113 additions & 0 deletions analysis/comms/sband.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#!/usr/bin/env python

# standard libraries
import os
import shutil
import subprocess

# third-party libraries
import numpy as np
import matplotlib.pyplot as plt
import pylink

sat_pattern = pylink.pattern_generator(3)

sat_rf_chain = [
pylink.Element(name="Cables", gain_db=-0.05, noise_figure_db=0.75),
pylink.Element(name="Filter", gain_db=-3.5, noise_figure_db=3.5),
pylink.Element(name="Demodulator", gain_db=0, noise_figure_db=15),
]

gs_rf_chain = [
pylink.Element(name="Cables", gain_db=-0.75, noise_figure_db=0.75), # TODO measure
pylink.Element(name="LNA", gain_db=35, noise_figure_db=2.75), # TODO double check
pylink.Element(name="Filter", gain_db=-3.5, noise_figure_db=3.5),
pylink.Element(name="Demodulator", gain_db=0, noise_figure_db=15),
]

geometry = pylink.Geometry(
apoapsis_altitude_km=450, periapsis_altitude_km=450, min_elevation_deg=20
)

sat_rx_antenna = pylink.Antenna( # TODO figure out whether there is geometry and what pointing assumptions are made
gain=3,
polarization="RHCP",
pattern=sat_pattern, # TODO double check what this means
rx_noise_temp_k=1000,
is_rx=True,
tracking=False,
)

sat_tx_antenna = pylink.Antenna(
gain=3, polarization="RHCP", pattern=sat_pattern, is_rx=False, tracking=False
)

gs_rx_antenna = pylink.Antenna(
pattern=pylink.pattern_generator(48), # TODO what does this mean
rx_noise_temp_k=300,
polarization="RHCP",
is_rx=True,
tracking=True,
)

gs_tx_antenna = pylink.Antenna(gain=25, polarization="RHCP", is_rx=False, tracking=True)

sat_receiver = pylink.Receiver(
rf_chain=sat_rf_chain, implementation_loss_db=2, name="Satellite SBand Receiver"
)

gs_receiver = pylink.Receiver(rf_chain=gs_rf_chain, name="Ground SBand Receiver")

gs_transmitter = pylink.Transmitter(
tx_power_at_pa_dbw=23, name="Ground SBand Transmitter"
)

sat_transmitter = pylink.Transmitter(
tx_power_at_pa_dbw=1.5, name="Satellite SBand Transmitter"
)

rx_interconnect = pylink.Interconnect(is_rx=True)


tx_interconnect = pylink.Interconnect(is_rx=False)

s_channel = pylink.Channel(
bitrate_hz=500e3, # TODO double check
allocation_hz=5e6, # TODO double check
center_freq_mhz=2450.0,
atmospheric_loss_db=0.5,
ionospheric_loss_db=0.5,
rain_loss_db=1,
multipath_fading_db=0,
polarization_mismatch_loss_db=3,
)

# defaults to DVB-S2X
modulation = pylink.Modulation(name="p2400 345.6") # TODO add frequency hopping scheme

DOWNLINK = pylink.DAGModel(
[
geometry,
gs_rx_antenna,
sat_transmitter,
sat_tx_antenna,
gs_receiver,
s_channel,
rx_interconnect,
tx_interconnect,
modulation,
pylink.LinkBudget(name="SBand Downlink", is_downlink=True),
]
)

UPLINK = pylink.DAGModel(
[
geometry,
sat_rx_antenna,
sat_receiver,
gs_transmitter,
gs_tx_antenna,
s_channel,
pylink.LinkBudget(name="SBand Uplink", is_downlink=False),
]
)
Loading