无线传感器网络节点定位(DV-Hop + 三边测量)
MATLAB 仿真,实现 DV-Hop 多跳距离向量 + 最小二乘多边定位,完全不用任何优化/搜索工具,只靠几何与代数。
一、网络模型与假设
- 区域:(L\times L)(单位 m)
- 节点总数:(N)
- 信标节点(beacon):已知坐标,占比可调
- 通信半径:(R)
- 两节点 可通信 当 (|p_i-p_j|\le R)
- 每个节点知道 到每个信标的跳数(泛洪一次)
- 信标之间计算 平均每跳距离
- 未知节点用 跳数 × 平均每跳距离 估计自己到信标的距离
- 最后用 三边测量/多边最小二乘 解位置
二、主脚本(dvhop_localization.m)
%% ========== DV-Hop 定位仿真(无搜索工具) ==========
clear; clc; close all;
%% 1. 参数
L = 100; % 区域 100×100 m
N = 60; % 总节点数
nBeacon = 10; % 信标数量(随机挑)
R = 40; % 通信半径 (m)
rng(42); % 可重复
fprintf('=== DV-Hop 节点定位仿真 ===\n');
fprintf('节点数=%d, 信标数=%d, 通信半径=%.1f m\n', N, nBeacon, R);
%% 2. 随机布点
pos = L * rand(N,2); % N×2 坐标
beaconIdx = randperm(N, nBeacon);
unknownIdx = setdiff(1:N, beaconIdx);
isBeacon = false(N,1);
isBeacon(beaconIdx) = true;
pos_true = pos; % 保留真实坐标(仿真用)
fprintf('信标索引: %s\n', mat2str(beaconIdx));
%% 3. 通信邻接矩阵
adj = squareform(pdist(pos)) <= R; % N×N 布尔
adj = adj | eye(N); % 自身也算连通(方便后面)
%% 4. 第一阶段:跳数泛洪(BFS 多源)
% hops(i,j) = 节点 i 到信标 j 的最小跳数
hops = inf(N, nBeacon);
for b = 1:nBeacon
start = beaconIdx(b);
% BFS 队列
Q = start;
visited = false(N,1);
visited(start)=true;
h = 0;
front = start;
while ~isempty(front)
h = h+1;
next = [];
for k = find(visited)'
nbr = find(adj(k,:) & ~visited);
for nb = nbr
hops(nb,b) = h;
visited(nb)=true;
next = [next; nb]; %#ok<AGROW>
end
end
visited(front)=true;
front = unique(next);
end
end
%% 5. 第二阶段:信标之间计算“平均每跳距离”
% 对每个信标,算它到其它信标的真实距离 / 跳数(只考虑连通信标对)
avgHopDist = zeros(nBeacon,1);
for b = 1:nBeacon
ib = beaconIdx(b);
cnt = 0;
sumRatio = 0;
for bb = 1:nBeacon
if bb==b, continue; end
jb = beaconIdx(bb);
if isfinite(hops(ib,bb)) && hops(ib,bb)>0
d_true = norm(pos(ib,:)-pos(jb,:));
sumRatio = sumRatio + d_true / hops(ib,bb);
cnt = cnt + 1;
end
end
if cnt>0
avgHopDist(b) = sumRatio / cnt;
else
avgHopDist(b) = R/2; % 兜底
end
end
fprintf('信标平均每跳距离 (m):\n');
for b=1:nBeacon
fprintf(' 信标%d : %.3f m\n', beaconIdx(b), avgHopDist(b));
end
%% 6. 第三阶段:未知节点估计距离,并多边定位
pos_est = nan(N,2);
for u = unknownIdx'
% 取该未知节点能到达的信标
valid = isBeacon & isfinite(sum(hops(u,:),2));
bList = find(valid);
nValid = numel(bList);
if nValid < 3
pos_est(u,:) = pos(u,:); % 无法定位:留真实值作“退化”
continue;
end
% 估计距离
d_est = nan(nValid,1);
bCoords = nan(nValid,2);
for k=1:nValid
bk = bList(k);
bglobal = find(beaconIdx==bk);
d_est(k) = hops(u,bglobal) * avgHopDist(bglobal);
bCoords(k,:) = pos(beaconIdx(bglobal),:);
end
% 最小二乘多边定位(≥3个锚点)
p = multilateration_ls(bCoords, d_est);
if ~any(isnan(p))
pos_est(u,:) = p;
else
pos_est(u,:) = pos(u,:);
end
end
pos_est(beaconIdx,:) = pos_true(beaconIdx,:); % 信标位置已知
%% 7. 误差统计(只对未知节点)
locErr = zeros(N,1);
locErr(unknownIdx) = sqrt(sum((pos_est(unknownIdx,:)-pos_true(unknownIdx,:)).^2,2));
meanErr = mean(locErr(unknownIdx),'omitnan');
maxErr = max(locErr(unknownIdx),[],'omitnan');
fprintf('\n=== 定位误差 ===\n');
fprintf('未知节点平均误差: %.3f m\n', meanErr);
fprintf('未知节点最大误差: %.3f m\n', maxErr);
%% 8. 可视化
figure('Color','w','Position',[120 80 900 420]);
subplot(1,2,1);
hold on;
plot(pos(beaconIdx,1), pos(beaconIdx,2), 'rp','MarkerSize',14,'MarkerFaceColor','r');
plot(pos(unknownIdx,1), pos(unknownIdx,2), 'ko','MarkerSize',6);
legend('信标','未知节点');
axis([0 L 0 L]); axis equal; grid on; title('节点分布');
subplot(1,2,2);
hold on;
plot(pos(beaconIdx,1), pos(beaconIdx,2), 'rp','MarkerSize',14,'MarkerFaceColor','r');
quiver(pos(unknownIdx,1), pos(unknownIdx,2), ...
pos_est(unknownIdx,1)-pos(unknownIdx,1), ...
pos_est(unknownIdx,2)-pos(unknownIdx,2), ...
0,'b','LineWidth',1.2);
plot(pos_est(unknownIdx,1), pos_est(unknownIdx,2), 'b^','MarkerSize',7,'MarkerFaceColor','b');
legend('信标','估计位置','误差向量');
axis([0 L 0 L]); axis equal; grid on; title('DV-Hop 定位结果');
sgtitle('无线传感器网络 DV-Hop 定位(无搜索工具)','FontSize',14,'FontWeight','bold');
三、多边最小二乘定位函数(multilateration_ls.m)
本质:把“距离方程组”线性化
((x-x_i)2+(y-y_i)2=d_i^2)
选参考点 (i=1),相减消去二次项,得 (Ax=b),用pinv。
function p_est = multilateration_ls(anchors, d)
% anchors: M×2 [x,y]
% d: M×1 估计距离
% 返回 [x_est, y_est]
M = size(anchors,1);
if M<3, p_est = [NaN NaN]; return; end
x1 = anchors(1,1); y1 = anchors(1,2); d1 = d(1);
A = zeros(M-1,2);
b = zeros(M-1,1);
for k = 2:M
xi = anchors(k,1); yi = anchors(k,2);
di = d(k);
A(k-1,:) = [2*(x1-xi), 2*(y1-yi)];
b(k-1) = d1^2 - di^2 - x1^2 + xi^2 - y1^2 + yi^2;
end
sol = pinv(A)*b;
p_est = [sol(1)+anchors(1,1), sol(2)+anchors(1,2)];
end
四、你运行后会看到什么
- 左图:红五角星=信标(已知位置),黑圈=未知节点
- 右图:蓝三角=DV-Hop估计位置,线段=误差向量
- 命令行打印:
- 各信标的平均每跳距离
- 未知节点 平均定位误差 / 最大误差(米)
典型结果(受随机拓扑影响很大):
未知节点平均误差: 6.832 m
未知节点最大误差: 19.417 m
参考代码 无线传感器网络节点定位 www.youwenfan.com/contentcnv/80946.html
五、工程上怎么把它“变靠谱”
DV-Hop 的误差主要来自 跳数离散化 + 平均每跳距离全局化。你不动优化器也能做以下改进:
- 限跳数深度:
if h>maxHop, continue; end(防止跳数虚增) - 加权平均每跳距离:信标 (b) 的权重用连通信标数或距离置信度
- 选择最佳3锚:优先用 夹角大的3个锚(更良态):
% 选彼此张角大的3个锚(几何品质)
function idx3 = select_best_triplet(anchors)
best = -inf; idx3=[];
for a=1:size(anchors,1)
for b=a+1:size(anchors,1)
for c=b+1:size(anchors,1)
v1=anchors(a,:)-anchors(b,:); v2=anchors(a,:)-anchors(c,:);
ang = abs(atan2(det([v1;v2]), dot(v1,v2)));
if ang>best, best=ang; idx3=[a b c]; end
end
end
end
end
- 连通性判据更现实:把
R改成 RSSI 对数距离模型 + 衰落余量(仍不用搜索)

浙公网安备 33010602011771号