Как обмениваться сигналами между разными программами при помощи 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
