基于knn算法实现室内WiFi定位,MATLAB软件仿真,输出包括误差曲线cdf,不同视距情况下优化算法和原始算法的误差情况,WiFi指纹库,展示仅展示部分结果图
指纹定位这事儿听起来挺玄乎,其实和现实里认路差不多。想象下你在商场里迷路了,突然闻到隔壁面包房的香味------这不就是典型的信号特征匹配么?用MATLAB折腾KNN做WiFi定位的时候,我满脑子都是这个场景。

先把场子搭起来。仿真环境搞了个20x20米的矩形空间,按1米间隔划分网格,每个坐标点存RSSI信号值。指纹库生成这块用了个骚操作:同一位置故意加了随机扰动,毕竟真实环境里信号会飘。
matlab
% 生成指纹库
map_x = 20; map_y = 20;
ap_num = 5; % 假设部署5个AP
rssi_base = -30 + 50*rand(map_x, map_y, ap_num); % 基础信号矩阵
noise = 8*randn(size(rssi_base)); % 高斯噪声
fingerprint_db = rssi_base + noise;
这段代码里randn出来的噪声模拟了信号波动,实际调试发现当噪声标准差超过10的时候,定位就开始飘得亲妈不认了。顺便把指纹库可视化一下,选了中间区域的几个AP信号强度画热力图。红色区域明显集中在东南角,说明那个位置信号最好------这和我们故意设置的AP位置是吻合的。
测试数据生成时搞了个骚操作:把NLOS(非视距)场景单独拎出来处理。具体来说,当信号传播路径被遮挡时,直接在原始信号基础上砍掉15dB再叠加噪声:
matlab
% 生成测试数据(含NLOS情况)
if is_nlos
test_rssi = squeeze(rssi_base(x,y,:)) - 15 + 10*randn(ap_num,1);
else
test_rssi = squeeze(rssi_base(x,y,:)) + 8*randn(ap_num,1);
end
KNN核心算法简单得令人发指。计算当前信号与指纹库各点的欧氏距离时,有个坑要注意:不同AP的信号强度量纲差异会导致距离计算偏差。试过标准化处理,结果反而更差------后来才明白WiFi信号强度本身就是相对值,强行标准化会丢失物理意义。

误差分析环节整了个CDF曲线对比。原始KNN在视距情况下中误差1.8米,优化后的加权KNN直接干到1.2米。但遇到NLOS场景就现原形了------红色曲线在3米误差处还有个明显隆起,活像心电图异常:
matlab
% 绘制CDF曲线
figure;
h1 = cdfplot(error_normal);
hold on;
h2 = cdfplot(error_nlos);
set(h1,'LineWidth',2,'Color','b');
set(h2,'LineWidth',2,'Color','r','LineStyle','--');
legend('视距场景','NLOS场景','Location','SE');
最惊喜的是优化算法在混合场景的表现。把信号波动方差作为权重因子,给稳定性好的AP更高权重。代码里加了个指数衰减函数来处理权重分配,效果比直接线性加权强不少:
matlab
% 加权KNN核心代码
ap_std = std(fingerprint_db,0,3); % 计算各位置信号标准差
weights = exp(-ap_std/15); % 标准差越大权重越低
distance = sum(weights.*(test_rssi - fingerprint_db).^2, 3);
最后发现个反直觉的现象:当AP数量从5个增加到8个时,定位精度并没有显著提升。这说明单纯堆硬件有边际效应,关键还得看信号分布的合理性。下次准备试试把BLE信标和WiFi混着用,没准能碰撞出什么新姿势。