python-vor


Namepython-vor JSON
Version 0.0.4 PyPI version JSON
download
home_pageNone
SummaryA small library to calculate the bearing of a VOR signal from a WAV file.
upload_time2025-07-11 18:36:41
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords vor bearing airports location navigation signal processing
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Python VOR Decoder

This repository contains a pure Python implementation of a VOR (VHF Omnidirectional Range) radio navigation signal decoder. The code is based on and adapted from the work of [martinber](https://github.com/martinber/vor-python-decoder), with additional comments, explanations, and minor modifications for clarity and usability.

## Overview

> [!NOTE]
> This library only decodes VOR signals from WAV files. It does not handle real-time signal processing or live VOR reception.

VOR is a type of radio navigation system for aircraft, allowing pilots to determine their position and bearing relative to a ground-based VOR station. This decoder processes a WAV file recording of a VOR signal and extracts the bearing information using digital signal processing techniques.

### VOR technical details

![RF Spectrum of the VRN airport VOR](https://raw.githubusercontent.com/iu2frl/PythonVOR/main/imgs/VOR_Spectrum.png)

VOR systems operate in the VHF range (108.0-117.95 MHz with 50 kHz spacing), with the lower 4 MHz shared with ILS frequencies. The VOR signal encodes directional information through the phase relationship between two 30 Hz signals. In Conventional VORs (CVOR), a 30 Hz reference signal is FM-modulated on a 9,960 Hz subcarrier while a variable 30 Hz AM signal is created by a rotating antenna.

> [!NOTE]
> This library only decodes VOR signals and not DVOR (Doppler VOR) signals. The decoding logic is designed specifically for Conventional VORs.

Doppler VORs (DVOR) use a fixed circular array of omnidirectional antennas, reversing the modulation roles: the reference is AM-modulated while the variable signal uses electronic switching to create FM through the Doppler effect.

Both types also transmit a station identifier in 7 WPM Morse code and often include an AM voice channel. Aircraft receivers determine bearing by measuring the phase difference between these reference and variable signals, with identical decoding regardless of VOR type.

This is exactly what this decoder does: it processes a recorded VOR signal, extracts the reference and variable components, demodulates them, and calculates the bearing based on their phase difference.

## Features

- **Pure Python implementation** using NumPy, SciPy, and Matplotlib
- **Signal processing pipeline** including:
  - Lowpass and bandpass FIR filtering
  - Sample rate decimation
  - FM subcarrier demodulation and phase extraction
  - Cross-correlation for phase comparison
- **Visualization** of signals in both time and frequency domains at each processing step
- **Calibration support** for phase alignment

## Testing

I tested the code using the signal from the VRN airport in Verona (115.800MHz), Italy. The code successfully decoded the VOR signal and displayed the correct bearing with a small approximation.

### Test points

![Map of the test points](https://raw.githubusercontent.com/iu2frl/PythonVOR/main/imgs/VRN_map.png)

The following test points were used, with their respective bearings:

| Latitude | Longitude | Measured Bearing | Displayed Bearing |
|----------|-----------|------------------|-------------------|
| 45.377740N | 10.880124E | 211° | 210° |
| 45.392627N | 10.905900E | 181° | 182° |
| 45.409503N | 10.883784E | 275° | 275° |
| 45.412321N | 10.900993E | 322° | 320° |
| 45.418328N | 10.930478E | 58°  | 58°  |

## Usage

### WAV recording

**Record a VOR signal** as a WAV file (mono or stereo). The recording should capture both the AM reference and FM variable signals.

- The receiver should be set to AM mode with a bandwidth of 22KHz
- Recording should be saved with a minimum sample rate of 48KHz (96KHz preferred)
- There is no need to record more than 1 second of audio, as the decoder processes the signal in chunks.

### Calculating using Jupyter Notebook

The Jupyter Notebook at [VOR_Decoder.ipynb](https://github.com/iu2frl/PythonVOR/blob/main/VOR_Decoder.ipynb) provides an interactive environment to process the recorded WAV file and extract the bearing.

It displays the decoding steps, including the original signal, filtered signals, and the final bearing result with visualizations.

1. **Set the `FILENAME` variable** in the notebook or script to point to your WAV file.
1. **Run the notebook or script** to process the signal and extract the bearing.

### Calculating using Python library

1. Install the library using pip: `pip install python-vor`
2. Import the `get_bearing` function from the library: `from python_vor import get_bearing`
3. Call the function with the WAV file path and optional parameters:

```python
from python_vor import get_bearing
file_path = "path/to/your/vor_signal.wav"
offset = 223  # Optional offset to add in the VOR calculation
bearing = get_bearing(file_path, offset=offset)
print(f"Bearing for file at {file_path} is: {bearing:.2f}°")
```

### Processing details

The processing steps include:

- Loading and displaying audio statistics
- Filtering and decimating the reference and variable signals
- Demodulating the FM subcarrier
- Extracting and filtering the variable signal phase
- Comparing phases to compute the bearing

## Dependencies

- numpy
- scipy
- matplotlib (only for the Jupyter Notebook visualization)

Install them via pip if needed:

```bash
pip install scipy==1.16.0
pip install numpy==2.3.1
```

## Contributing

Please refer to the [CONTRIBUTING.md](https://github.com/iu2frl/PythonVOR/blob/main/CONTRIBUTING.md) file for guidelines on contributing to this project.

## Attribution

Original code and algorithm by [martinber](https://github.com/martinber/vor-python-decoder).  
This repository provides a cleaned-up and commented version for educational and practical use.

## License

This project is licensed under the MIT License. See the [LICENSE](https://github.com/iu2frl/PythonVOR/blob/main/LICENSE) file for details.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "python-vor",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "vor, bearing, airports, location, navigation, signal processing",
    "author": null,
    "author_email": "Luca Bennati <lucabennati1996@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/b8/4b/37650b3cfc68c27b2159dac51058cd76c2ade1e6f815e63b981c615c8af8/python_vor-0.0.4.tar.gz",
    "platform": null,
    "description": "# Python VOR Decoder\n\nThis repository contains a pure Python implementation of a VOR (VHF Omnidirectional Range) radio navigation signal decoder. The code is based on and adapted from the work of [martinber](https://github.com/martinber/vor-python-decoder), with additional comments, explanations, and minor modifications for clarity and usability.\n\n## Overview\n\n> [!NOTE]\n> This library only decodes VOR signals from WAV files. It does not handle real-time signal processing or live VOR reception.\n\nVOR is a type of radio navigation system for aircraft, allowing pilots to determine their position and bearing relative to a ground-based VOR station. This decoder processes a WAV file recording of a VOR signal and extracts the bearing information using digital signal processing techniques.\n\n### VOR technical details\n\n![RF Spectrum of the VRN airport VOR](https://raw.githubusercontent.com/iu2frl/PythonVOR/main/imgs/VOR_Spectrum.png)\n\nVOR systems operate in the VHF range (108.0-117.95 MHz with 50 kHz spacing), with the lower 4 MHz shared with ILS frequencies. The VOR signal encodes directional information through the phase relationship between two 30 Hz signals. In Conventional VORs (CVOR), a 30 Hz reference signal is FM-modulated on a 9,960 Hz subcarrier while a variable 30 Hz AM signal is created by a rotating antenna.\n\n> [!NOTE]\n> This library only decodes VOR signals and not DVOR (Doppler VOR) signals. The decoding logic is designed specifically for Conventional VORs.\n\nDoppler VORs (DVOR) use a fixed circular array of omnidirectional antennas, reversing the modulation roles: the reference is AM-modulated while the variable signal uses electronic switching to create FM through the Doppler effect.\n\nBoth types also transmit a station identifier in 7 WPM Morse code and often include an AM voice channel. Aircraft receivers determine bearing by measuring the phase difference between these reference and variable signals, with identical decoding regardless of VOR type.\n\nThis is exactly what this decoder does: it processes a recorded VOR signal, extracts the reference and variable components, demodulates them, and calculates the bearing based on their phase difference.\n\n## Features\n\n- **Pure Python implementation** using NumPy, SciPy, and Matplotlib\n- **Signal processing pipeline** including:\n  - Lowpass and bandpass FIR filtering\n  - Sample rate decimation\n  - FM subcarrier demodulation and phase extraction\n  - Cross-correlation for phase comparison\n- **Visualization** of signals in both time and frequency domains at each processing step\n- **Calibration support** for phase alignment\n\n## Testing\n\nI tested the code using the signal from the VRN airport in Verona (115.800MHz), Italy. The code successfully decoded the VOR signal and displayed the correct bearing with a small approximation.\n\n### Test points\n\n![Map of the test points](https://raw.githubusercontent.com/iu2frl/PythonVOR/main/imgs/VRN_map.png)\n\nThe following test points were used, with their respective bearings:\n\n| Latitude | Longitude | Measured Bearing | Displayed Bearing |\n|----------|-----------|------------------|-------------------|\n| 45.377740N | 10.880124E | 211\u00b0 | 210\u00b0 |\n| 45.392627N | 10.905900E | 181\u00b0 | 182\u00b0 |\n| 45.409503N | 10.883784E | 275\u00b0 | 275\u00b0 |\n| 45.412321N | 10.900993E | 322\u00b0 | 320\u00b0 |\n| 45.418328N | 10.930478E | 58\u00b0  | 58\u00b0  |\n\n## Usage\n\n### WAV recording\n\n**Record a VOR signal** as a WAV file (mono or stereo). The recording should capture both the AM reference and FM variable signals.\n\n- The receiver should be set to AM mode with a bandwidth of 22KHz\n- Recording should be saved with a minimum sample rate of 48KHz (96KHz preferred)\n- There is no need to record more than 1 second of audio, as the decoder processes the signal in chunks.\n\n### Calculating using Jupyter Notebook\n\nThe Jupyter Notebook at [VOR_Decoder.ipynb](https://github.com/iu2frl/PythonVOR/blob/main/VOR_Decoder.ipynb) provides an interactive environment to process the recorded WAV file and extract the bearing.\n\nIt displays the decoding steps, including the original signal, filtered signals, and the final bearing result with visualizations.\n\n1. **Set the `FILENAME` variable** in the notebook or script to point to your WAV file.\n1. **Run the notebook or script** to process the signal and extract the bearing.\n\n### Calculating using Python library\n\n1. Install the library using pip: `pip install python-vor`\n2. Import the `get_bearing` function from the library: `from python_vor import get_bearing`\n3. Call the function with the WAV file path and optional parameters:\n\n```python\nfrom python_vor import get_bearing\nfile_path = \"path/to/your/vor_signal.wav\"\noffset = 223  # Optional offset to add in the VOR calculation\nbearing = get_bearing(file_path, offset=offset)\nprint(f\"Bearing for file at {file_path} is: {bearing:.2f}\u00b0\")\n```\n\n### Processing details\n\nThe processing steps include:\n\n- Loading and displaying audio statistics\n- Filtering and decimating the reference and variable signals\n- Demodulating the FM subcarrier\n- Extracting and filtering the variable signal phase\n- Comparing phases to compute the bearing\n\n## Dependencies\n\n- numpy\n- scipy\n- matplotlib (only for the Jupyter Notebook visualization)\n\nInstall them via pip if needed:\n\n```bash\npip install scipy==1.16.0\npip install numpy==2.3.1\n```\n\n## Contributing\n\nPlease refer to the [CONTRIBUTING.md](https://github.com/iu2frl/PythonVOR/blob/main/CONTRIBUTING.md) file for guidelines on contributing to this project.\n\n## Attribution\n\nOriginal code and algorithm by [martinber](https://github.com/martinber/vor-python-decoder).  \nThis repository provides a cleaned-up and commented version for educational and practical use.\n\n## License\n\nThis project is licensed under the MIT License. See the [LICENSE](https://github.com/iu2frl/PythonVOR/blob/main/LICENSE) file for details.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "A small library to calculate the bearing of a VOR signal from a WAV file.",
    "version": "0.0.4",
    "project_urls": {
        "Homepage": "https://github.com/iu2frl/python_vor",
        "Issues": "https://github.com/iu2frl/python_vor/issues",
        "Source": "https://github.com/iu2frl/python_vor"
    },
    "split_keywords": [
        "vor",
        " bearing",
        " airports",
        " location",
        " navigation",
        " signal processing"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "73ea042f506dbfc302e91102fef1b4e5ed7205a8d8e71878f8626cb10b67ddff",
                "md5": "3b2e3d9609c087b261894b960e017c64",
                "sha256": "87120aa7793d7c6ae1e310ed8bbfaa2799ee38ddc794150815877c517c41120b"
            },
            "downloads": -1,
            "filename": "python_vor-0.0.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "3b2e3d9609c087b261894b960e017c64",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 15097,
            "upload_time": "2025-07-11T18:36:40",
            "upload_time_iso_8601": "2025-07-11T18:36:40.011449Z",
            "url": "https://files.pythonhosted.org/packages/73/ea/042f506dbfc302e91102fef1b4e5ed7205a8d8e71878f8626cb10b67ddff/python_vor-0.0.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "b84b37650b3cfc68c27b2159dac51058cd76c2ade1e6f815e63b981c615c8af8",
                "md5": "67ba4eb9713e3b069792440808815ea4",
                "sha256": "07ce7acc1cfa05bd1f8ed80336565532023c663b4ae5bad6ca17e9dfef3c7e9d"
            },
            "downloads": -1,
            "filename": "python_vor-0.0.4.tar.gz",
            "has_sig": false,
            "md5_digest": "67ba4eb9713e3b069792440808815ea4",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 13146,
            "upload_time": "2025-07-11T18:36:41",
            "upload_time_iso_8601": "2025-07-11T18:36:41.545936Z",
            "url": "https://files.pythonhosted.org/packages/b8/4b/37650b3cfc68c27b2159dac51058cd76c2ade1e6f815e63b981c615c8af8/python_vor-0.0.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-11 18:36:41",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "iu2frl",
    "github_project": "python_vor",
    "github_not_found": true,
    "lcname": "python-vor"
}
        
Elapsed time: 2.53839s