Adding a Satellite

If a satellite uses a modulation and framing that gr-satellites already supports, adding it only takes a SatYAML file, with no code. This page walks through the whole process: identifying the protocol, writing and testing the file locally, validating it, adding a telemetry parser, and contributing it upstream.

When a SatYAML File Is Enough

Check the satellite's published radio parameters (or a recording) against the supported lists:

  • the modulations: FSK, AFSK, BPSK, DBPSK, Manchester variants, subaudio FSK;
  • the framings: AX.25, AX100, U482C, CCSDS, AO-40, NGHam, USP, OpenLST, ...

Many CubeSats use standard modems (GOMspace AX100, AX.25 TNCs, CCSDS-based radios), so a new satellite is often only a new combination of existing building blocks. If the framing is new, a new deframer component must be written in Python (see python/components/deframers/ for examples) and registered in gr_satellites_flowgraph._deframer_hooks and in SatYAML.framings in python/satyaml/satyaml.py.

Where SatYAML Files Live

Location Path
Source tree python/satyaml/*.yml
Installed the satellites/satyaml/ directory of the installed Python package

Find the installed directory with:

python3 -c "import satellites.satyaml, os; print(os.path.dirname(satellites.satyaml.__file__))"

Lookups by name and NORAD ID scan every *.yml file in that directory. A file copied there becomes selectable by name immediately; a file anywhere else can always be used by path.

Step 1: Write the File

Start from a bundled satellite with the same radio. For a satellite with a 9k6 FSK AX.25 G3RUH downlink whose telemetry format you do not know yet:

name: MY-SAT
alternative_names:
  - MYSAT-1
norad: 99999
data:
  &tlm Telemetry:
    unknown
transmitters:
  9k6 FSK downlink:
    frequency: 437.500e+6
    modulation: FSK
    baudrate: 9600
    framing: AX.25 G3RUH
    data:
    - *tlm

unknown prints every frame in hex, which is what you want until a parser exists. Remember:

  • norad must be an integer.
  • Write the frequency with a signed exponent (437.500e+6), or YAML reads it as a string.
  • Transmitter names appear in the output and in frame metadata; use descriptive names like 9k6 FSK downlink.
  • Add one entry under transmitters for each distinct baud rate or mode the satellite uses. They all run in parallel.

See the SatYAML Format reference for every field.

Step 2: Test with a Recording

Run it by path (the name must end in .yml):

gr_satellites ./MY-SAT.yml --wavfile my_sat_pass.wav

If nothing decodes, work through the tuning workflow: real vs IQ input, polarity (--input_gain -1), --clk_bw, and the verbose options of the deframer.

Step 3: Validate

Run the same checks as the project's unit test:

python3 -c "from satellites.satyaml import yamlfiles; yamlfiles.check_yaml('MY-SAT.yml')"

No output means the file passed. A YAMLError names the problem (see Validation for the messages and the checker's blind spots). The checker does not test whether the chosen framing accepts the deframer fields you used (frame size, scrambler, ...). That is only checked when the decoder is built, so the run from step 2 is the real test: a TypeError about an unexpected keyword argument means a field does not belong to that framing. gr_satellites ./MY-SAT.yml --help is a quick check that the file loads and that the options you expect are registered, but it exits before building the decoder.

Step 4: Add a Telemetry Parser

Once you know the frame layout, write a construct definition (see Writing a Telemetry Parser) and point the data entry at it:

data:
  &tlm Telemetry:
    telemetry: my_sat

If the satellite sends files or images, add a files: or image: entry with a file receiver.

Step 5: Contribute It

gr-satellites aims to support every satellite transmitting in the Amateur bands, so contributions are welcome:

  1. Add the .yml file to python/satyaml/. python/satyaml/CMakeLists.txt installs all *.yml files with a glob, so no CMake change is needed, but re-run cmake in your build directory so the new file is picked up by make install.
  2. Add any new telemetry parser to python/telemetry/__init__.py and python/telemetry/CMakeLists.txt (and any new file receiver to the corresponding files in python/filereceiver/).
  3. Run make test; the qa_satyaml test runs check_yaml() on every bundled file.
  4. Follow the contributing guidelines (PEP 8 checked by pycodestyle, commit message rules, the LLM usage policy) and open a pull request against main.

The list of supported satellites in the upstream Sphinx documentation (docs/source/supported_satellites.rst) is generated from the SatYAML files by docs/generate_supported_satellites.py.

Policies to be aware of

  • Satellite teams planning to use gr-satellites for their own ground station are encouraged to upstream support for their satellite rather than keep a fork, and to introduce themselves in the GitHub discussions "Satellite teams" category. See satellite_teams.md.
  • Commercial satellites: contributions specifically for receiving a commercial satellite are only accepted if the operator endorses or acknowledges them. Generic blocks are always accepted. See commercial_satellites.md.

See Also