ESPRIT算法时一种利用子空间旋转法估计DOA参数的方法,其算法的基本思想是将阵列在结构上分成两个完全一致的子列,两个子列相应阵元偏移的距离相等,也就是说阵列的阵元被分成一对对的形式,而且每一对之间具有相同的平移距离,这样入射角在两个子阵列上仅相差一个旋转不变因子,该因子包含了各个入射信号的波达方向信息,因此通过求解一个广义的特征值,就可以得到入射信号的DOA。该算法与MUSIC算法相比具有以下优点:
*无需精确知道阵列流形向量,仅需要各子阵列之间保持一致,因此降低了对阵列较准的严格性
*不需要在整个空间上进行DOA谱峰搜索从而极大地降低了计算量和存储量
主要步骤分为
旋转因子、建立方程
使用特征值分解工具:1)求非零广义特征值; 2)求伪逆; 3)LS-Esprit; 4)TLS-Esprit
LS-Esprit方法步骤
由阵列数据估计相关矩阵
对相关矩阵进行特征值分解
用P个大特征值对应的特征矢量构成子空间,并将其分成E_X和E_Y两部分
计算矩阵inv(E_X)*E_Y的特征值ξ
计算到达角
仿真结果
%LS_ESPRIT ALGORITHM
clear all;
%close all;
clc;
source_number=2;%信元数
sensor_number=8;%原阵元数
sub_sensor_number=7;%子阵元数
N_x=1024; %信号长度
snapshot_number=N_x;%快拍数
w=[pi/4 pi/6].';%信号频率
l=sum(2*pi*3e8./w)/length(source_number);%信号波长
d=0.5*l;%阵元间距
snr=0;%信噪比/dB
source_doa=[-10 60];%两个信号的入射角度
A=[exp(-1j*(0:sensor_number-1)*d*2*pi*sin(source_doa(1)*pi/180)/l);exp(-1j*(0:sensor_number-1)*d*2*pi*sin(source_doa(2)*pi/180)/l)].';%阵列流型
s=sqrt(10.^(snr/10))*exp(1j*w*[0:N_x-1]);%仿真信号
%x=A*s+(1/sqrt(2))*(randn(sensor_number,N_x)+1j*randn(sensor_number,N_x));%加了高斯白噪声后的阵列接收信号
x=awgn(A*s,10);
x1=x(1:sub_sensor_number,:);%子阵1接受的数据矢量
x2=x(2:(sub_sensor_number+1),:);%子阵2接受的数据矢量
%对两个子阵的模型进行合并
X=[x1;x2];
R=X*X'/snapshot_number;
%对R进行奇异值分解
[U,S,~]=svd(R);
%选择大的特征值构成空间并分成两部分
Us=U(:,1:source_number);
disp(Us);
Us1=Us(1:sub_sensor_number,:);
Us2=Us((sub_sensor_number+1):2*sub_sensor_number,:);
%按照公式得到旋转不变矩阵M
E=pinv(Us1)*Us2;
disp('E');
disp(E);
%对得到的旋转不变矩阵进行特征分解
[V,D]=eig(E);
disp('D');
disp(D);
D=(diag(D)).';
doa=-asin(angle(D)/pi)*180/pi;
doa=sort(doa);
polarplot(doa(1)*pi/180,1,'*',doa(2)*pi/180,1,'square');
grid on;
title('DOA Estimation by LS ESPRIT Algorithm with Monte Carlo');
hold on;
drawnow;
比较简单,从代码中我们可以看出算法中并未涉及阵列流形的计算,所以此方法将适用于阵列流形未知的情况。
TLS-Esprit方法步骤
由阵列数据估计相关矩阵
对相关矩阵进行特征值分解
用P个大特征值对应的特征矢量构成子空间,并将其分成E_X和E_Y两部分
计算矩阵(E_X)’*E_Y的特征向量,并将其分解为PXP的子阵[V_11 V_12; V_21 V_22]
计算V_12*inv(V_22)的特征值
计算到达角
与上述LS-Esprit方法多了几步而已,下面是仿真结果
%对两个子阵的模型进行合并
X=[x1;x2];
R=X*X'/snapshot_number;
%对R进行奇异值分解
[U,S,~]=svd(R);
Us=U(:,1:source_number);
disp(Us);
Us1=Us(1:sub_sensor_number,:);
Us2=Us((sub_sensor_number+1):2*sub_sensor_number,:);
%形成矩阵Us12
Us12=[Us1,Us2];
%对“Us12'*Us12”进行特征分解,得到矩阵F
[F,Sa,Va]=svd(Us12'*Us12);
disp('F');
disp(F);
disp(Sa);
%将F分解为四个小矩阵
F11=F(1:2,1:2);
F12=F(1:2,3:4);
F21=F(3:4,1:2);
F22=F(3:4,3:4);
%按照公式得到旋转不变矩阵E
E=-(F12*(inv(F22)));
disp('E');
disp(E);
%对得到的旋转不变矩阵进行特征分解
[V,D]=eig(E);
disp(D);
D=(diag(D)).';
doa=-asin(angle(D)/pi)*180/pi;
doa=sort(doa);
LS与TLS的Esprit算法对比
针对单一信号源的DOA估计,根据快拍数以及信噪比的不同分别进行1000次蒙特卡洛仿真,后求取估计的RMSE的平均值,实验代码较为简单这里不再给出了,下面直接给出结果。
本文主要实现了基础的EESPRIT算法仿真,包括LS跟TLS,并对两种方法进行了蒙特卡洛仿真,从结果上来看,ESPRIT算法由于不需要角度搜索从而大大提升了算法的运行效率;LS与TLS两者效果差不多,如果后续有些新的理解再来进行修改。
本文未给出一些详细的公式推导,如果后续有时间,将对这一部分进行补充。
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in
我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby-vips的github页面上的链接,我们将不胜感激!如果有ruby-
我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d
给定两个大小相等的数组,如何找到不考虑位置的匹配元素的数量?例如:[0,0,5]和[0,5,5]将返回2的匹配项,因为有一个0和一个5共同;[1,0,0,3]和[0,0,1,4]将返回3的匹配项,因为0有两场,1有一场;[1,2,2,3]和[1,2,3,4]将返回3的匹配项。我尝试了很多想法,但它们都变得相当粗糙和令人费解。我猜想有一些不错的Ruby习惯用法,或者可能是一个正则表达式,可以很好地回答这个解决方案。 最佳答案 您可以使用count完成它:a.count{|e|index=b.index(e)andb.delete_at
我正在尝试解析网页,但有时会收到404错误。这是我用来获取网页的代码:result=Net::HTTP::getURI.parse(URI.escape(url))如何测试result是否为404错误代码? 最佳答案 像这样重写你的代码:uri=URI.parse(url)result=Net::HTTP.start(uri.host,uri.port){|http|http.get(uri.path)}putsresult.codeputsresult.body这将打印状态码和正文。