Как обмениваться сигналами между разными программами при помощи LSL (Lab Streaming Layer)
Для реализации новых идей и алгоритмов обработки сигналов зачастую хочется сконцентрировать свои усилия на математике и программировании, а не на разработке всех аппаратно-программных устройств получения этих сигналов на низком уровне. Для этого лучшим выходом является обмен сигналами по стандартному протоколу, такому как Lab Streaming Layer (LSL). Ранее в проекте LD.Connect уже был применен похожий вариант соединения — протокол UDP. Но гораздо удобнее использовать специализированный интерфейс, т.к. его поддерживают различные исследовательские системы, например OpenVibe, Matlab, Python и др.
Поговорим как это происходит на примере среды Python, как лидирующего языка программирования в области обработки сигналов.
Для получения сигнала через LSL Вам не надо знать структуру данных, адрес передатчика, влезать в чужую программу и т.п. Просто запрашиваете нужный сигнал и получаете поток данных с которым делаете что угодно и в реальном времени!
Установка модуля pylsl в Python
Для этого просто воспользуемся пакетным менеджером PIP. В командном окне (терминале) наберите следующую команду:
pip install pylsl
Модуль скачается и будет доступен.
Организация python программы передатчика сигнала LSL
Для эмуляции передачи некого сигнала передатчика по Lab Streaming Layer, создадим файл и вставим следующий код:
"""Пример программы для отправки многоканальных данных по протоколу LSL""" from random import random as rand from pylsl import StreamInfo, StreamOutlet, local_clock def main(): srate = 500 # Частота дискретизации name = 'LabData' # Название источника sigtype = 'Random signal' # Название сигнала n_channels = 2 # Число каналов info = StreamInfo(name, sigtype, n_channels, srate, 'float32', 'labdata.ru') outlet = StreamOutlet(info) print("Начало отправки данных...") start_time = local_clock() sent_samples = 0 while True: elapsed_time = local_clock() - start_time required_samples = int(srate * elapsed_time) - sent_samples for sample_ix in range(required_samples): # Создаем новый набор случайных данных mysample = [rand(), rand()] # Два канала, но может быть больше # Отправка outlet.push_sample(mysample) sent_samples += required_samples if __name__ == '__main__': main()
Здесь происходит объявление имени источника, типа сигнала (в данном случае просто случайный сигнал), формат чисел — float32 — число с плавающей точкой и идентификатором устройства (в данном примере labdata.ru)
В цикле происходит генерация двух случайных чисел (двух каналов) и отправка по LSL.
Пояснения смотрите в видеообзоре.
Организация python программы приема сигнала LSL
Для получения сигнала по Lab Streaming Layer, создадим файл и вставим следующий код:
"""Пример программы для получения многоканальных данных по протоколу LSL""" from pylsl import StreamInlet, resolve_stream def main(): print("Ожидание данных...") streams = resolve_stream('type', 'Random signal') # Ищем нужный сигнал # Создаем вход для получения данных inlet = StreamInlet(streams[0]) while True: # Получение нового измерения sample, timestamp = inlet.pull_sample() print(timestamp, sample) if __name__ == '__main__': main()
Как можно заметить, программа получения предельно проста! Выполняется в три этапа: Создается описание потока данных streams, где указывает какой тип сигнала нужен, затем открываем входной поток inlet, а потом в цикле опрашиваем его функцией pull_sample(), забирая переданный список каналов и таймкод (его брать не обязательно).
Далее с полученными значениями sample можно делать что угодно.
Видеообзор
Видеопояснения с демонстрацией работы можете посмотреть далее.
Как можете заметить, в обмене данных через протокол Lab Streaming Layer (LSL) нет ничего сложного. В последствии он будет использован в проектах LabData.ru.
Вопросы и предложения можете задать в группе ВК, телеграмм, разделе Сотрудничество и на канале Youtube.
(с) Роман В. Исаков, 2023