[Python, Беспроводные технологии] ModulationPy: цифровые схемы модуляции на языке Python
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Привет, Хабр! Сегодня хочу поделиться своим небольшим домашним проектом:
ModulationPy (GitHub)
- модуль для моделирования цифровых схем модуляции (это которые PSK, QAM и т.п.). Проект был вдохновлен другой питоновской библиотекой: CommPy; однако, в рассмотренном классе задач с ней удалось даже немного посоревноваться!
Сигнальное созвездие 16-QAM сгенерированное и отрисованное с помощью ModulationPyНа данный момент доступны два класса схем модуляции:
- M-PSK: Phase Shift Keying (фазовая цифровая модуляция)
- M-QAM: Quadratured Amplitude Modulation (квадратурная амплитудная модуляция)где M - это порядок модуляции.
Интересен модуль может быть, скорее всего, в разрезе образовательных целей в сфере беспроводной связи (подбор модуляций исходил именно из нее), однако, вдруг кому-то пригодится и для научных изысканий. Не MatLab'ом насущным едины!
Примеры использованияИтак, для начала скачиваем библиотеку с PyPI:
$ pip install ModulationPy
Либо устанавливаем из исходников, но на PyPI на момент написания статьи все-таки актуальная версия. Зависимости две:
- numpy>=1.7.1
- matplotlib>=2.2.2 (для построения сигнальных созвездий)
Продемонстрируем на деле.Итак, например, мы хотим использовать QPSK с поворотом фазы pi/4, двоичным входом и наложением по Грею (Gray mapping). Импортируем и инициализируем:
import numpy as np
from ModulationPy import PSKModem
modem = PSKModem(4, np.pi/4,
gray_map=True,
bin_input=True)
Проверяем то ли мы инициализировали, нарисовав сигнальное созвездие методом plot_const():
modem.plot_const()
Сигнальное созвездие QPSK с поворотом фазы pi/4, двоичным входом и наложением по Грею (Gray mapping)То же самое сделаем для 16-QAM (но для десятичных чисел на входе; указывать фазовый сдвиг не нужно - подразумевается наиболее распространенная прямоугольная QAM):
from ModulationPy import QAMModem
modem = QAMModem(16,
gray_map=True,
bin_input=False)
modem.plot_const()
Сигнальное созвездие 16-QAM с десятичным входом и наложением по Грею (Gray mapping)На данный момент модуляция QAM реализована по примеру функции qammod в Octave [4]. И, да, реализованы только «четные» (в том смысле, что результат log2(M) - четное число) схемы модуляции (4-QAM, 16-QAM, 64-QAM). Пусть и не совсем полный набор, но как бы то ни было, в популярных стандартах беспроводной связи все равно нет "нечетных" схем модуляции (насколько я знаю).Далее предлагаю перейти, собственно, к главному в модемах: к модуляции и демодуляции. Для этого нам понадобятся два метода:modulate() и demodulate() , доступные в обоих классах.Метод modulate() принимает на вход всего один аргумент:
- вектор входных значений (1-D ndarray of ints) - либо единиц и нулей, если выбрана опция bin_input=True , либо целых десятичных чисел от 0 до M-1, если bin_input=False ;
Методdemodulate() ожидает максимум два аргумента:
- вектор, который должен быть демодулирован (1-D ndarray of complex symbols) ;
- значение дисперсии аддитивного шума (float, по умолчанию 1.0).
Например, вот как это будет выглядеть для QPSK (двоичный вход/выход):
import numpy as np
from ModulationPy import PSKModem
modem = PSKModem(4, np.pi/4,
bin_input=True,
soft_decision=False,
bin_output=True)
msg = np.array([0, 0, 0, 1, 1, 0, 1, 1]) # input message
modulated = modem.modulate(msg) # modulation
demodulated = modem.demodulate(modulated) # demodulation
print("Modulated message:\n"+str(modulated))
print("Demodulated message:\n"+str(demodulated))
>>> Modulated message:
[0.70710678+0.70710678j 0.70710678-0.70710678j
-0.70710678+0.70710678j -0.70710678-0.70710678j]
>>> Demodulated message:
[0. 0. 0. 1. 1. 0. 1. 1.]
Или тоже QPSK, но уже с недвоичным входом / выходом:
import numpy as np
from ModulationPy import PSKModem
modem = PSKModem(4, np.pi/4,
bin_input=False,
soft_decision=False,
bin_output=False)
msg = np.array([0, 1, 2, 3]) # input message
modulated = modem.modulate(msg) # modulation
demodulated = modem.demodulate(modulated) # demodulation
print("Modulated message:\n"+str(modulated))
print("Demodulated message:\n"+str(demodulated))
>>> Modulated message:
[ 0.70710678+0.70710678j -0.70710678+0.70710678j 0.70710678-0.70710678j
-0.70710678-0.70710678j]
>>> Demodulated message:
[0, 1, 2, 3]
Пример для 16-QAM (десятичный вход / выход):
import numpy as np
from ModulationPy import QAMModem
modem = PSKModem(16,
bin_input=False,
soft_decision=False,
bin_output=False)
msg = np.array([i for i in range(16)]) # input message
modulated = modem.modulate(msg) # modulation
demodulated = modem.demodulate(modulated) # demodulation
print("Demodulated message:\n"+str(demodulated))
>>> Demodulated message:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
В общем и целом, я думаю, понятно. Доступные опции старался делать по примеру доступных в рамках матлабовского Communication Toolbox. Подробное описание приведено в README.md проекта. BER performanceПродемонстрируем адекватно ли модемы работают в случае присутствия шума (возьмем классический АБГШ, он же AWGN), используя простейшую модель приема-передачи:
Структурная схема системы, состоящий из передатчика (источник сообщения, модулятор), канала (AWGN) и приемника (демодулятор и модуль подсчитывающий ошибки демодуляции).Сверяться будем с теоретическими кривыми [5] (если кому интересно, все формулы описаны тоже в README.md).
Результаты:
Кривые битовых ошибок для AWGN (M-PSK).
Кривые битовых ошибок для AWGN (M-QAM).Да, с огрехами на малых значениях битовых ошибок (из-за относительно небольшого количества усреднений, я полагаю), однако.... it works! ПроизводительностьА теперь я хотел бы вернуться к вопросу "соревнования" с упомянутой выше CommPy. Что нас отличает:
- организация кода, стилистические различия (побочное, но не пренебрежимое);
- я использовал более быстрый алгоритм демодуляции [6] (подробно описан в матлабовской документации [7], ну, и я добавил все в тот же README.md).
И вот, что получилось "забенчмаркать":
- Скрипт: CommPy_vs_ModulationPy.ipynb
- Платформа: https://jupyter.org/try (Classic Notebook)
- Длина фрейма: 10 000 (элементов)
Результаты:Метод (библиотека)Среднее время исполнения (мс)modulation (ModulationPy): QPSK10.3modulation (CommPy): QPSK15.7demodulation (ModulationPy): QPSK0.4demodulation (CommPy): QPSK319modulation (ModulationPy): 256-QAM8.9modulation (CommPy): 256-QAM11.3demodulation (ModulationPy): 256-QAM42.6demodulation (CommPy): 256-QAM22 000Разработчикам CommPy результаты, вроде, понравились (см. данный issue) - поэтому возможно в обозримом будущем что-то из моего ModulationPy будет перекочевывать в CommPy (я не против, главное, чтобы пользу приносило). Но это, как говорится, поживем - увидим.И, да, пусть результаты производительности и не дотянули до MatLab (по крайней мере исходя из данного примера: см. вкладку "Examples"), я все равно считаю достигнутое неплохим стартом!ПослесловиеНаверное, проекту не хватает еще некоторых видов модуляции (тех же 32-QAM и 128-QAM или же используемой в DVB-S2/S2X APSK), однако, честно скажу, что не могу обещать их скорого добавления. Проект всегда был для меня в большей мере площадкой для изучения языка Python и библиотеки NumPy на практике (и сопутствующих инструментов: юнит-тесты (не успел правда в данном случае перейти на pytest - каюсь), CI (использую Travis), подготовка модуля для PyPi и т.д.), однако, теперь, слава богу, всему этому есть приложение и в рамках рабочих задач!Однако, все же буду рад вашим issue и pull request'ам! И если возьметесь интегрировать наработки в CommPy, тоже будет очень круто! В общем, не серчайте, если вдруг не отвечу достаточно быстро, и да пребудет с вами сила науки! Литература и ссылки
- Haykin S. Communication systems. – John Wiley & Sons, 2008. — p. 93
- Goldsmith A. Wireless communications. – Cambridge university press, 2005. – p. 88-92
- MathWorks: comm.PSKModulator (https://www.mathworks.com/help/comm/ref/comm.pskmodulator-system-object.html?s_tid=doc_ta)
- Octave: qammod (https://octave.sourceforge.io/communications/function/qammod.html)
- Link Budget Analysis: Digital Modulation, Part 3 (www.AtlantaRF.com)
- Viterbi, A. J. (1998). An intuitive justification and a simplified implementation of the MAP decoder for convolutional codes. IEEE Journal on Selected Areas in Communications, 16(2), 260-264.
- MathWorks: Approximate LLR Algorithm (https://www.mathworks.com/help/comm/ug/digital-modulation.html#brc6ymu)
===========
Источник:
habr.com
===========
Похожие новости:
- [Python, Программирование] Шифрование сообщений в RYTHON. От простого к сложному. Шифр Цезаря
- [Python, Flask] Телеграмм-бот на Python
- [Сетевые технологии, Беспроводные технологии, Разработка систем связи, Научно-популярное, Космонавтика] Всё о проекте «Спутниковый интернет Starlink». Часть 27 Первые итоги. Часть вторая — проблемная
- [Python, Профессиональная литература] Книга «Современный скрапинг веб-сайтов с помощью Python. 2-е межд. издание»
- [Python, Программирование] «За что вы так меня не любите?» (с) Python
- [Беспроводные технологии, Разработка систем связи, Космонавтика] Аналитики раскритиковали интернет Starlink от SpaceX
- [Python, Программирование, Разработка робототехники, Робототехника] Как установить ROS NOETIC на UBUNTU 20.04
- [Python, Django, Nginx] Развертывание приложений Django
- [Беспроводные технологии, Разработка систем связи, Законодательство в IT, Космонавтика] OneWeb построит три наземные станции в России для обеспечения доступа в интернет
- [Python] Обработка и анализ текстов на Python и Spark NLP
Теги для поиска: #_python, #_besprovodnye_tehnologii (Беспроводные технологии), #_python3, #_numpy, #_petproject, #_python, #_besprovodnye_tehnologii (
Беспроводные технологии
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:40
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Привет, Хабр! Сегодня хочу поделиться своим небольшим домашним проектом: ModulationPy (GitHub)
Сигнальное созвездие 16-QAM сгенерированное и отрисованное с помощью ModulationPyНа данный момент доступны два класса схем модуляции:
Примеры использованияИтак, для начала скачиваем библиотеку с PyPI: $ pip install ModulationPy
import numpy as np
from ModulationPy import PSKModem modem = PSKModem(4, np.pi/4, gray_map=True, bin_input=True) modem.plot_const()
Сигнальное созвездие QPSK с поворотом фазы pi/4, двоичным входом и наложением по Грею (Gray mapping)То же самое сделаем для 16-QAM (но для десятичных чисел на входе; указывать фазовый сдвиг не нужно - подразумевается наиболее распространенная прямоугольная QAM): from ModulationPy import QAMModem
modem = QAMModem(16, gray_map=True, bin_input=False) modem.plot_const() Сигнальное созвездие 16-QAM с десятичным входом и наложением по Грею (Gray mapping)На данный момент модуляция QAM реализована по примеру функции qammod в Octave [4]. И, да, реализованы только «четные» (в том смысле, что результат log2(M) - четное число) схемы модуляции (4-QAM, 16-QAM, 64-QAM). Пусть и не совсем полный набор, но как бы то ни было, в популярных стандартах беспроводной связи все равно нет "нечетных" схем модуляции (насколько я знаю).Далее предлагаю перейти, собственно, к главному в модемах: к модуляции и демодуляции. Для этого нам понадобятся два метода:modulate() и demodulate() , доступные в обоих классах.Метод modulate() принимает на вход всего один аргумент:
import numpy as np
from ModulationPy import PSKModem modem = PSKModem(4, np.pi/4, bin_input=True, soft_decision=False, bin_output=True) msg = np.array([0, 0, 0, 1, 1, 0, 1, 1]) # input message modulated = modem.modulate(msg) # modulation demodulated = modem.demodulate(modulated) # demodulation print("Modulated message:\n"+str(modulated)) print("Demodulated message:\n"+str(demodulated)) >>> Modulated message: [0.70710678+0.70710678j 0.70710678-0.70710678j -0.70710678+0.70710678j -0.70710678-0.70710678j] >>> Demodulated message: [0. 0. 0. 1. 1. 0. 1. 1.] import numpy as np
from ModulationPy import PSKModem modem = PSKModem(4, np.pi/4, bin_input=False, soft_decision=False, bin_output=False) msg = np.array([0, 1, 2, 3]) # input message modulated = modem.modulate(msg) # modulation demodulated = modem.demodulate(modulated) # demodulation print("Modulated message:\n"+str(modulated)) print("Demodulated message:\n"+str(demodulated)) >>> Modulated message: [ 0.70710678+0.70710678j -0.70710678+0.70710678j 0.70710678-0.70710678j -0.70710678-0.70710678j] >>> Demodulated message: [0, 1, 2, 3] import numpy as np
from ModulationPy import QAMModem modem = PSKModem(16, bin_input=False, soft_decision=False, bin_output=False) msg = np.array([i for i in range(16)]) # input message modulated = modem.modulate(msg) # modulation demodulated = modem.demodulate(modulated) # demodulation print("Demodulated message:\n"+str(demodulated)) >>> Demodulated message: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] Структурная схема системы, состоящий из передатчика (источник сообщения, модулятор), канала (AWGN) и приемника (демодулятор и модуль подсчитывающий ошибки демодуляции).Сверяться будем с теоретическими кривыми [5] (если кому интересно, все формулы описаны тоже в README.md). Результаты: Кривые битовых ошибок для AWGN (M-PSK). Кривые битовых ошибок для AWGN (M-QAM).Да, с огрехами на малых значениях битовых ошибок (из-за относительно небольшого количества усреднений, я полагаю), однако.... it works! ПроизводительностьА теперь я хотел бы вернуться к вопросу "соревнования" с упомянутой выше CommPy. Что нас отличает:
=========== Источник: habr.com =========== Похожие новости:
Беспроводные технологии ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:40
Часовой пояс: UTC + 5