Я пытаюсь работать над проектом, связанным с внедрением моделей акустических потерь при распространении в подводной связи (на основе определенного исследовательского документа). Мы пытаемся смоделировать это в unetstack
. Конечной целью является создание класса модели канала, в котором реализованы все модели потерь.
Но сейчас мы начали с попытки отправить сигнал основной полосы частот с одного узла на другой, а затем пытаемся зафиксировать частоту на узле-приемнике и рассчитать модели потерь на этой заданной частоте. (Модели потерь являются функцией значения частоты сигнала). Я пытался следовать некоторой документации и некоторым сообщениям в блогах, но я не могу передавать и получать сигнал.
Для справки я уже ссылался на эти статьи: 1.) SVC-12-основной диапазон 2.) базовые операции с модемом с использованием unetstack
Это исследовательская работа, которой я следую это для расчета убытков на основе различных моделей убытков.
Я попытался написать отличный файл для моделирования, но он не работает. Если кто-то может посмотреть и сообщить мне ошибки, которые я сделал, это было бы реальной помощью. Мы новичок в 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 определенной частоты. Таким образом, когда node2 получает сигнал, он может извлечь и изменить частоту сигнала. Итак, не могли бы вы предложить некоторые изменения в коде, чтобы этого можно было достичь? Спасибо
Базовый код, который у вас есть для передачи (TxBasebandSignalReq
) и приема (RecordBasebandSignalReq
) сигналов, кажется правильным.
Это должно хорошо работать на модемах, за исключением того факта, что ваше генерирование сигнала, вероятно, ошибочно по двум причинам:
Вы пытаетесь сгенерировать сигнал с частотой 5 кГц в представлении основной полосы частот, используя несущую частоту 24 кГц и полосу пропускания 24 кГц. Этот сигнал будет сглажен, так как это представление основной полосы частот может представлять только сигналы 24 ± 12 кГц, т. е. 12–36 кГц. Если вам нужно передать сигнал 5 кГц, вам нужно, чтобы ваш модем работал на гораздо более низкой несущей частоте (легко в симуляторе, но на практике вам нужно проверить характеристики модема).
Вы преобразуете вывод 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"
})
}
}
Это должно работать так, как ожидалось!
Тем не менее, есть еще несколько ошибок, о которых следует помнить:
Вы отправляете и записываете по таймеру. В симуляторе это должно быть нормально, так как оба узла имеют одинаковое время начала и нет задержки распространения (вы установили узлы в одном и том же месте). Однако на реальном модеме запись может не происходить во время передачи.
Передача и прием сигналов с настоящим модемом работает хорошо. Симулятор Unet в первую очередь является симулятором сети и фокусируется на моделировании поведения модемов в системе связи, но не обязательно на акустическом распространении. Хотя он поддерживает сервис BASEBAND
, физика канала передачи сигналов не точно моделируется моделью HalfDuplexModem
по умолчанию. Таким образом, ваш пробег по обработке сигнала записи может варьироваться. Это можно исправить, определив собственную модель канала, которая использует подходящую модель акустического распространения, но это нетривиальная задача.
Не могли бы вы объяснить, что вы подразумеваете под «похоже, что это не работает»? Каково ваше ожидаемое поведение и что вы видите? Поскольку поведение тикера запускается в одно и то же время и имеет одинаковый период, порядок срабатывания может быть либо узел 1, затем 2, либо узел 2, а затем 1.