Как передавать и принимать сигнал основной полосы в unetstack? - PullRequest
2 голосов
/ 08 апреля 2019

Я пытаюсь работать над проектом, включающим реализацию моделей потерь на акустическое распространение в подводной связи (на основе определенной исследовательской работы).Мы пытаемся смоделировать это в unetstack.Конечная цель - создать класс модели канала, в котором реализованы все модели потерь.

Но сейчас мы начали с попытки отправки сигнала основной полосы частот от одного узла к другому, а затем пытаемся захватить частотуна узле приемника и рассчитать модели потерь на данной частоте.(Модели потерь являются функцией значения частоты сигнала).Я пытался следовать некоторой документации и некоторым постам в блоге, но я не могу передавать и получать сигнал.

Для справки, я уже ссылался на эти статьи: 1.) svc-12-baseband 2.) basic-modem-operations-using-unetstack

Это исследовательская работа, за которой я следую this для расчета потерь на основеразные модели потерь.

Я пытался написать отличный файл для моделирования, но, похоже, он не работает.Если кто-то может, пожалуйста, взглянуть и сообщить мне об ошибках, которые я допустил, это очень поможет.Мы довольно плохо знакомы с unetstack, а также с темой подводной обработки сигналов, и это наша первая попытка реализовать ее на симуляторе.Мы используем unetsim-1.3

Любая помощь очень ценится!Заранее спасибо

import org.arl.fjage.*
import org.arl.unet.*
import org.arl.unet.phy.*
import org.arl.unet.bb.*
import org.arl.unet.sim.*
import org.arl.unet.sim.channels.*
import static org.arl.unet.Services.*
import static org.arl.unet.phy.Physical.*

import java.lang.Math.*

platform = RealTimePlatform

simulate 3.minutes, {
    def n = []
    n << node('1', address: 1, location: [0,0,0])
    n << node('2', address: 2, location: [0,0,0])

    n.eachWithIndex { n2, i ->

        n2.startup = {
            def phy = agentForService PHYSICAL
            def node = agentForService NODE_INFO
            def bb = agentForService BASEBAND
            subscribe phy
            subscribe bb

            if(node.address == 1)
            {
                add new TickerBehavior(50000, {

                    float freq = 5000
                    float duration = 1000e-3
                    int fd = 24000
                    int fc = 24000
                    int num = duration*fd
                    def sig = []
                    (0..num-1).each { t ->
                        double a = 2*Math.PI*(freq-fc)*t/fd
                        sig << (int)(Math.cos(a))
                        sig << (int)(Math.sin(a))
                    }

                    bb << new TxBasebandSignalReq(signal: sig)
                    println "sent"
                })

            }

            if(node.address == 2)
            {
                add new TickerBehavior(50000, { 
                    bb << new RecordBasebandSignalReq(recLen: 24000)
                    def rxNtf = receive(RxBasebandSignalNtf, 25000)
                    if(rxNtf)
                    {
                        println "Received"
                    }

                    println "Tried"
                })              
            }
        }
    } 
}

В некоторых случаях «Пробный» печатается первым даже до того, как «отправленный» напечатан.Это показывает, что код (node.address == 2) выполняется первым, прежде чем (node.address == 1) выполняется.

1 Ответ

2 голосов
/ 10 апреля 2019

Базовый код, который вы используете для передачи (TxBasebandSignalReq) и приема (RecordBasebandSignalReq) сигналов, кажется правильным.

Это должно хорошо работать на модемах, за исключением того факта, что генерация вашего сигнала, вероятно, имеет недостатки по 2 причинам:

  1. Вы пытаетесь сгенерировать сигнал с частотой 5 кГц в представлении основной полосы частот, используя несущую частоту 24 кГц и ширину полосы 24 кГц. Этот сигнал будет псевдонимом, так как это представление основной полосы частот может представлять только сигналы 24 ± 12 кГц, то есть 12–36 кГц. Если вам нужно передать сигнал 5 кГц, вам нужно, чтобы модем работал на гораздо более низкой несущей частоте (это легко сделать в симуляторе, но на практике вам необходимо проверить характеристики модема).

  2. Вы вводите выходные данные с sin и cos до int. Вероятно, это не то, что вы намеревались сделать, поскольку signal - это массив float, масштабируемый между -1 и 1. Поэтому было бы целесообразно просто удалить (int).

В симуляторе вам необходимо убедиться, что параметры модема настроены правильно, чтобы отражать ваши предположения о частоте несущей основной полосы, ширине полосы и длине записи:

modem.carrierFrequency = 24000
modem.basebandRate = 24000
modem.maxSignalLength = 24000

Параметры по умолчанию HalfDuplexModem отличаются, и ваш текущий код не будет работать для RecordBasebandSignalReq с ответом REFUSE (который ваш код не проверяет).

Остальная часть вашего кода выглядит хорошо, но я бы немного упростил его до:

import org.arl.fjage.*
import org.arl.unet.bb.*
import org.arl.unet.Services

platform = RealTimePlatform

modem.carrierFrequency = 24000
modem.basebandRate = 24000
modem.maxSignalLength = 48000

simulate 3.minutes, {

  def n1 = node('1', address: 1, location: [0,0,0])
  def n2 = node('2', address: 2, location: [0,0,0])

  n1.startup = {
    def bb = agentForService Services.BASEBAND
    add new TickerBehavior(50000, {
      float freq = 25000  // pick a frequency in the 12-36 kHz range
      float duration = 1000e-3
      int fd = 24000
      int fc = 24000
      int num = duration*fd
      def sig = []
      (0..num-1).each { t ->
        double a = 2*Math.PI*(freq-fc)*t/fd
        sig << Math.cos(a)
        sig << Math.sin(a)
      }
      bb << new TxBasebandSignalReq(signal: sig)
      println "sent"
    })
  }

  n2.startup = {
    def bb = agentForService Services.BASEBAND
    add new TickerBehavior(50000, {
      bb << new RecordBasebandSignalReq(recLen: 24000)
      def rxNtf = receive(RxBasebandSignalNtf, 25000)
      if(rxNtf) {
        println "Received"
      }
      println "Tried"
    })
  }

}

Это должно работать как положено!

Однако есть еще несколько ошибок, о которых следует помнить:

  1. Вы отправляете и записываете по таймеру. На симуляторе это должно быть хорошо, так как оба узла имеют одинаковое время начала и не имеют задержки распространения (вы настроили узлы в одном и том же месте). Однако на реальном модеме запись может не происходить, когда происходит передача.

  2. Хорошо работает передача и прием сигналов с помощью реального модема. Симулятор Unet - это, в первую очередь, симулятор сети, который предназначен для моделирования поведения модемов в системе связи, но не обязательно для распространения звука. Хотя он поддерживает службу BASEBAND, физика канала передачи сигналов не точно смоделирована моделью по умолчанию HalfDuplexModem. Так что ваш пробег при обработке сигнала записи может отличаться. Это можно исправить, определив собственную модель канала, в которой используется подходящая модель распространения звука, но это нетривиальное мероприятие.

...