无线传感器网络节点定位(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 的误差主要来自 跳数离散化 + 平均每跳距离全局化。你不动优化器也能做以下改进:

  1. 限跳数深度if h>maxHop, continue; end(防止跳数虚增)
  2. 加权平均每跳距离:信标 (b) 的权重用连通信标数或距离置信度
  3. 选择最佳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
  1. 连通性判据更现实:把 R 改成 RSSI 对数距离模型 + 衰落余量(仍不用搜索)
posted @ 2026-06-15 16:21  hczyydqq  阅读(8)  评论(0)    收藏  举报