【问题标题】:How to transmit and receive a baseband signal in unetstack?如何在unetstack中发送和接收基带信号?
【发布时间】:2019-04-08 09:18:27
【问题描述】:

我正在尝试一个项目,该项目涉及在水下通信中实施声传播损耗模型(基于某篇研究论文)。我们正在尝试在unetstack 中进行模拟。最终目标是创建一个实现了所有损失模型的通道模型类。

但现在我们已经开始尝试从一个节点向另一个节点发送基带信号,然后尝试捕获接收节点上的频率并计算该给定频率上的损耗模型。 (损耗模型是信号频率值的函数)。我尝试关注一些文档和一些博客文章,但我无法发送和接收信号。

作为参考,我已经参考了这些文章: 1.) svc-12-baseband 2.) basic-modem-operations-using-unetstack

这是我关注this 的研究论文,用于根据不同的损失模型计算损失。

我曾尝试编写一个 groovy 文件进行模拟,但它似乎不起作用。如果有人可以请看一下并让我知道我所犯的错误,那将是真正的帮助。我们对 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) 执行之前首先执行。

【问题讨论】:

  • 您能解释一下“它似乎不起作用”是什么意思吗?您的预期行为是什么,您看到了什么?由于ticker行为同时启动且周期相同,触发顺序可以是节点1后2,也可以是节点2后1。
  • 我们的目标是从node1向node2发送一个特定频率的基带信号。因此,node2在接收到信号时,可以提取和修改信号的频率。那么,您能否建议对代码进行一些修改以实现它?谢谢

标签: groovy unetstack


【解决方案1】:

您用于传输 (TxBasebandSignalReq) 和接收 (RecordBasebandSignalReq) 信号的基本代码似乎是正确的。

这应该在调制解调器上运行良好,除了您的信号生成可能存在缺陷的事实有 2 个原因:

  1. 您正尝试使用 24 kHz 的载波频率和 24 kHz 的带宽以基带表示生成 5 kHz 的信号。此信号将被混叠,因为此基带表示只能表示 24±12 kHz 的信号,即 12-36 kHz。如果您需要传输 5 kHz 信号,则需要调制解调器以低得多的载波频率运行(在模拟器中很容易,但实际上您需要检查调制解调器规格)。

  2. 您正在将sincos 的输出类型转换为int。这可能不是您打算做的,因为 signal 是一个在 -1 和 1 之间缩放的 float 数组。因此建议删除 (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 模型无法准确地模拟传输信号的通道物理特性。因此,您对录音信号处理的里程可能会有所不同。这可以通过定义您自己的通道模型来解决,该模型使用适当的声学传播模型,但这是一项艰巨的任务。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    • 2020-05-11
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    相关资源
    最近更新 更多