KerberosSDR代码笔记(6) 仿真程序

接下来的内容比较简单,讲一下几个用来仿真的程序。用这些程序在调试过程中,可以脱离kerberossdr硬件,会方便好多。

分别是sim.sh,_receiver/C下的sim.c以及_dataFiles下的DOA_sim_gen.py和sim_gen.py

先来看看sim.sh

#!/bin/bash

echo "Starting Hydra offline test"
rm _receiver/C/gate_control_fifo
mkfifo _receiver/C/gate_control_fifo

rm _receiver/C/sync_control_fifo
mkfifo _receiver/C/sync_control_fifo

#python3 _GUI/hydra_main_window.py &
./_receiver/C/sim  2>log_err_sim 1| ./_receiver/C/sync 2>log_err_sync 1| ./_receiver/C/gate 2>log_err_gate 1| python3 _GUI/hydra_main_window.py

它与run.sh很像,主要的区别是启动的时候把./_receiver/C/rtl_daq的部分换成了./_receiver/C/sim,由仿真程序输出数据给后面的程序,而不是由rtlsdr硬件给出,另外,每个程序它都记录了log。

接下来看看sim.c

/* KerberosSDR DAQ
 *
 * Copyright (C) 2018-2019  Carl Laufer, Tamás Pető
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 *
 */

#include 
#include 
#include 
#include 

#define CH_NO 4 // Number of channels
#define BUFFER_SIZE 1024*512


int main()
{   
    fprintf(stderr, "Hydra test started \n");		
    int success = 1;
    char filename[32];    
    size_t read_len;
    
    FILE **fds; // File descriptor array
    fds = malloc(CH_NO * sizeof(*fds));
    
    uint8_t **buffers;
    buffers = malloc(CH_NO *sizeof(*buffers)); 
    //初始化buffers指针,每个接收机通道都会有一个这个指针所以大小要乘以CH_NO
    for (int m=0; m

接下来讲_dataFiles下的两个python程序,它们各自都可以单独用来生成仿真数据,先看sim_gen.py

# -*- coding: utf-8 -*-
import numpy as np
from struct import pack
import matplotlib.pyplot as plt

fname_template = "sim" #文件名开头
ch_no = 4 #通道总数
delays = [0, 10, 20, 30] #几个通道的延迟大小
phase_shifts=[0, 45, 0,0] #几个通道的相位差
blocks = 100 #有多少个标准长度
block_size = 1024*512 #标准长度大小注意这里和使用硬件时的1024*256不同,但是与sim.c相符

fds= [] # File descriptors
for m in range(ch_no):
    fname=fname_template+str(m)+".iq"    #生成文件名,每个通道一个文件
    fds.append( open(fname, 'w+b', buffering=0)) 
    #打开文件,存入fds数组,数组元素是每个通道的iq数据的文件
print("All files opened")
signal = np.zeros((block_size), dtype=np.uint8)
#这是用来存储当前要发送的通道的数据的一维数组
raw_sig_nch = np.zeros((ch_no, block_size), dtype=np.uint8) 
#这是用来存储生成的4个通道数据的二维数组
for b in range(blocks):
    print("Writing block: %d"%b)
    raw_sig = np.random.normal(0,1,(block_size//2+max(delays)))+1j*np.random.normal(0,1,(block_size//2+max(delays)))
    #生成一组原始数据,它们在-1~1中间变化,均值为0,标准差为1
    #由于它在后面作为复数的模,复数表示的话长度减半,所以长度是block_size//2
    #但是这组数据要给其它几个通道生成延时后的数据的,所以要足够长,这样人为延迟后数据还够用
    #就要在原来的长度上加上最大的延迟
    #raw_sig = np.exp(1j*2*np.pi*(100/(block_size//2+max(delays))) * np.arange((block_size//2+max(delays))))
    #有了基础数据后就可以对各通道逐一生成数据了
    for m in range(ch_no):        
        raw_sig_m = raw_sig*np.exp(1j*np.deg2rad(phase_shifts[m]))  
        #每个通道使用的模都来在raw_sig,但是各通道都乘以了一个e^(j*phi)
        #也就是说相对于基础数据的每个采样点,后面的3个通道的每个相应采样点都相对移动了一个
        #固定的相位差,每个通道的相位差都是各自的phase_shifts[m]只是同一通道的这个相位差不变 
        raw_sig_m += (1+1j)
        raw_sig_m *= (255/2)
        #这里做的是把-1~1映射为了0~255,同样对虚部也是一样的操作
        raw_sig_nch[m,0::2] = raw_sig_m.real[delays[m]:delays[m]+block_size//2]
        raw_sig_nch[m,1::2] = raw_sig_m.imag[delays[m]:delays[m]+block_size//2]
        #接下来要对raw_sig_m做延迟处理,方法是获得对应通道的延迟delays[m]
        #然后在处理完的基础数据的数组上直接跳过delays[m]个采样点,就算做好延迟了
        #为了存储和发送,这里把raw_sig_m的实部和虚部分开了
        #本来应该从0开始到block_size//2(因为一半是i另一半是q),现在延迟delays[m]个
        #就是从raw_sig_m的delays[m]开始,到delays[m]+block_size//2结束
        #生成完了以后要存入raw_sig_nch二维数组,横坐标m是通道号
        #纵坐标,0开始是实部,1开始是虚部,然后一列隔一列存所以步进是2
        
        
        signal[0::2] = raw_sig_m.real[delays[m]:delays[m]+block_size//2]
        signal[1::2] = raw_sig_m.imag[delays[m]:delays[m]+block_size//2] 
        #signal也是类似的,它相当于是raw_sig_nch的其中一行,也就是当前处理的这个通道的iq数据     
        byte_array= pack('B'*block_size, *signal)         
        #最后往文件里写的是signal就行了,因为文件里只需要一维的数据,把单个通道的存入一个文件
        fds[m].write(byte_array)       
        #注意这样每个通道对应一个iq文件,里面只有这个通道的iq数据
for f in fds:
    f.close()
#最后把4个通道的文件句柄关闭掉
print("Al files are closed")
"""
iq_samples = np.zeros((ch_no, block_size//2), dtype=complex)
for m in range(ch_no):   
    real = raw_sig_nch[m, 0 ::2]
    imag = raw_sig_nch[m, 1::2]
    iq_samples[m,:].real, iq_samples[m,:].imag = real, imag
    iq_samples /= (255 / 2)
    iq_samples -= (1 + 1j)
pw=2**15
offset = 50000
delay = 0
phasors = (iq_samples[0, offset: pw+offset] * iq_samples[1, offset+delay: pw+offset+delay].conj())
phasors /= np.abs(phasors)
#K = 1000
#plt.scatter(phasors.real, phasors.imag)
xw = np.abs(np.fft.fft(iq_samples[1,:]))
#plt.plot(iq_samples[3,:].imag)
plt.plot(xw)
"""

上面这个生成的iq文件,应该只是测延迟和相位校准算法的,不是测doa算法的,下面这个才是。

接下来看DOA_sim_gen.py

# -*- coding: utf-8 -*-
import os
import sys
import numpy as np
from struct import pack


# Import the pyArgus module
root_path = os.path.pardir#getcwd()
pyargus_path = os.path.join(os.path.join(root_path, "pyArgus"), "pyArgus")
sys.path.insert(0, pyargus_path)
import directionEstimation_v1p15 as de
#要生成doa的数据要引用pyargus库的de包

####################################
#           PARAMETERS 
####################################

fname_template = "sim"
ch_no = 4
delays = [0, 0, 0, 0]
phase_shifts=[0, 0, 0,0]
blocks = 100
block_size = 1024*512


pn = 10**-3 # Noise power #噪声功率
fds= [] # File descriptors

# Antenna system parameters
M = 4  # Number of antenna elemenets 
UCA_radius = 0.5  # [wavelength]
ULA_spacing = 0.5 # [wavelength]
DOAs =  np.linspace(0,360, blocks)
antenna_array_type = "UCA"

if antenna_array_type == "UCA":
    x = UCA_radius * np.cos(2*np.pi/M * np.arange(M))
    y = UCA_radius * np.sin(-2*np.pi/M * np.arange(M))
    array_resp_vectors = de.gen_scanning_vectors(M, x, y, DOAs)
    #生成扫描向量
elif antenna_array_type == "ULA":    
    x = np.arange(M) * ULA_spacing
    y = np.zeros(M)
    array_resp_vectors = de.gen_scanning_vectors(M, x, y, DOAs)
    
else:
    print("[ ERROR ] Unidentified antenna array alignment")


####################################
#            Simulation
####################################

# Opening simulation files
for m in range(ch_no):
    fname=fname_template+str(m)+".iq"    
    fds.append( open(fname, 'w+b', buffering=0))
print("[ INFO ] All files opened")


signal = np.zeros((block_size), dtype=np.uint8)
raw_sig_nch = np.zeros((ch_no, block_size), dtype=np.uint8)

for b in range(blocks):
    print("[ INFO ] Writing block: %d"%b)
    raw_sig = np.random.normal(0,1,(block_size//2+max(delays)))+1j*np.random.normal(0,1,(block_size//2+max(delays)))
    #生成原始信号,和上一个程序类似
    raw_sig /= np.max(np.abs(raw_sig))
    raw_sig *= np.max(np.abs(raw_sig))*0.9         
    #把生成的信号做归一化,再取最大值的90%
    #raw_sig = np.exp(1j*2*np.pi*(100/(block_size//2+max(delays))) * np.arange((block_size//2+max(delays))))
    
    
    for m in range(ch_no):
        noise = np.random.normal(0,pn,(block_size//2+max(delays)))+1j*np.random.normal(0,pn,(block_size//2+max(delays)))
        #生成噪声,是另一段随机数据,但是标准差是噪声功率pn,后面没用到
        # Use this to generate ULA simulation
        #raw_sig_m = raw_sig*np.exp(1j*2*np.pi*0.5*np.cos(np.deg2rad(0))*np.arange(4))[m]
        
        # Modifly the phase of received signal according to the realtive position of the element         #根据阵元的相对位置来改变接收到的信号的相位
        raw_sig_m = raw_sig*array_resp_vectors[m,b]
        #用扫描向量来改变相位
        
        raw_sig_m += (1+1j)
        #raw_sig_m *= (255/2)
        raw_sig_m *= (255/2)
        #数据范围映射
        raw_sig_nch[m,0::2] = raw_sig_m.real[delays[m]:delays[m]+block_size//2]
        raw_sig_nch[m,1::2] = raw_sig_m.imag[delays[m]:delays[m]+block_size//2]
        #延迟生成的方法和上一个程序一样
      
        signal[0::2] = raw_sig_m.real[delays[m]:delays[m]+block_size//2]
        signal[1::2] = raw_sig_m.imag[delays[m]:delays[m]+block_size//2]      
        byte_array= pack('B'*block_size, *signal)         
        fds[m].write(byte_array)       
        #最终文件生成的方法也和上一个程序一样
for f in fds:
    f.close()
print("[ DONE ] Al files are closed")

 

你可能感兴趣的:(KerberosSDR)