根据信号强度查找位置(圆圈之间的交叉区域)
Find Position based on signal strength (intersection area between circles)
我正在尝试根据从 4 个 Wi-Fi 接入点接收到的信号强度来估计位置。我测量了位于 100 平方米 (10x10) 方形房间每个角落的 4 个接入点的信号强度。我使用 Android phone 记录了已知位置 (x, y) = (9.5, 1.5) 的信号强度。现在我想检查在这种情况下多点定位方法的准确性。
使用 MATLAB,我应用了一个公式来使用信号强度计算距离。下面的 MATLAB 函数显示了公式的应用:
function [ d_vect ] = distance( RSS )
% Calculate distance from signal strength
result = (27.55 - (20 * log10(2400)) + abs(RSS)) / 20;
d_vect = power(10, result);
end
输入的RSS是在测试点(x,y) = (9.5, 1.5)测得的四个信号强度向量。 RSS 矢量如下所示:
RSS =
-57.6000
-60.4000
-44.7000
-54.4000
并且包含到每个接入点的所有估计距离的合成向量如下所示:
d_vect =
7.5386
10.4061
1.7072
5.2154
现在我想根据这些距离和接入点位置来估计我的位置,以便找到估计位置和已知位置(9.5,1.5)之间的误差。我想找到四个圆之间的交叉区域(为了估计一个位置),其中每个接入点是其中一个圆的中心,距离是圆的半径。
我想找到如图所示的灰色区域:
http://www.biologycorner.com/resources/venn4.gif
所以基本上你需要与 4 个圆相交。可以有很多方法,有两种方法可以生成准确的交叉区域。
第一种方法是从一个圆开始,将它与第二个圆相交,然后将所得区域与第三个圆相交,依此类推。也就是说,在每一步你都知道当前的交叉区域,并且你将它与一个新的圆相交。相交区域将始终是一个由圆弧包围的区域,因此要将它与一个新圆相交,您可以沿着该区域的边界行走并检查每个边界弧是否与一个新圆相交。如果是,那么你只留下位于新圆内的圆弧部分,记住你应该继续从新圆开始的圆弧,并继续穿过边界,直到找到下一个交点。
另一种方法似乎会导致更糟糕的时间复杂度,但在您有 4 个圆圈的情况下,这并不重要,即找到两个圆圈的所有交点并仅选择那些感兴趣的点你,就在所有其他圈子里。这些点将是您所在区域的角,然后重建该区域就相当容易了。谷歌搜索了一下后,我什至找到了 live demo of this approach.
如果您想使用另一种方法来估计位置而不估计圆的交点,您可以使用 trilateration。给定一组距离测量值来估计位置是导航(例如 GPS)中的一种常用技术。
另外,如果你想要这个区域,因为你还需要估计位置的不确定性,我建议使用 least squares 解决三边测量问题,这将很容易地给你一个涉及的参数的估计和一个错误传播以产生位置的不确定性。
我找到了一个完美解决问题的答案。在这个link中有详细解释:
https://gis.stackexchange.com/questions/40660/trilateration-algorithm-for-n-amount-of-points
我也针对这个问题开发了一些MATLAB代码。开始了:
估计与接入点的距离:
function [ d_vect ] = distance( RSS )
result = (27.55 - (20 * log10(2400)) + abs(RSS)) / 20;
d_vect = power(10, result);
end
三边测量函数:
function [] = trilat( X, d, real1, real2 )
cla
circles(X(1), X(5), d(1), 'edgecolor', [0 0 0],'facecolor', 'none','linewidth',4); %AP1 - black
circles(X(2), X(6), d(2), 'edgecolor', [0 1 0],'facecolor', 'none','linewidth',4); %AP2 - green
circles(X(3), X(7), d(3), 'edgecolor', [0 1 1],'facecolor', 'none','linewidth',4); %AP3 - cyan
circles(X(4), X(8), d(4), 'edgecolor', [1 1 0],'facecolor', 'none','linewidth',4); %AP4 - yellow
axis([0 10 0 10])
hold on
tbl = table(X, d);
d = d.^2;
weights = d.^(-1);
weights = transpose(weights);
beta0 = [5, 5];
modelfun = @(b,X)(abs(b(1)-X(:,1)).^2+abs(b(2)-X(:,2)).^2).^(1/2);
mdl = fitnlm(tbl,modelfun,beta0, 'Weights', weights);
b = mdl.Coefficients{1:2,{'Estimate'}}
scatter(b(1), b(2), 70, [0 0 1], 'filled')
scatter(real1, real2, 70, [1 0 0], 'filled')
hold off
结束
其中,
X:具有 AP 坐标的矩阵
d: 距离估计向量
real1: 真实位置 x
real2: 实际位置 y
如果您有三组测量值(x,y)位置坐标和相应的信号强度。如:
m1 = (x1,y1,s1)
m2 = (x2,y2,s2)
m3 = (x3,y3,s3)
然后您可以计算每个点位置之间的距离:
d12 = Sqrt((x1 - x2)^2 + (y1 - y2)^2)
d13 = Sqrt((x1 - x3)^2 + (y1 - y3)^2)
d23 = Sqrt((x2 - x3)^2 + (y2 - y3)^2)
现在考虑每个信号强度测量值表示该信号的发射器,该信号来自远处的某个位置。该距离将是测量信号强度的位置的半径,因为此时人们不知道信号来自的方向。另外,信号越弱……半径越大。换句话说,信号强度测量将与半径成反比。信号强度越小,半径越大,反之亦然。所以,计算我们三个点的比例半径,虽然还不准确:
r1 = 1/s1
r2 = 1/s2
r3 = 1/s3
所以现在,在每一对点上,根据它们的距离分开,我们可以计算一个常数 (C),其中每个位置的半径将刚好相互接触。例如,对于点对 1 和 2:
Ca * r1 + Ca * r2 = d12
...求解常数 Ca:
Ca = d12 / (r1 + r2)
...我们也可以对其他两对执行此操作。
Cb = d13 / (r1 + r3)
Cc = d23 / (r2 + r3)
好吧...select 最大的 C 常数,Ca、Cb 或 Cc。然后,使用圆的参数方程找到坐标相交的位置。我会解释。
圆的参数方程为:
x = radius * Cos(theta)
y = radius * Sin(theta)
如果 Ca 是找到的最大常数,那么您将比较点 1 和 2,例如:
Ca * r1 * Cos(theta1) == Ca * r2 * Cos(theta2) &&
Ca * r1 * Sin(theta1) == Ca * r2 * Sin(theta2)
...从 0 度到 360 度迭代 theta1 和 theta2,对于两个圆。您可以编写如下代码:
for theta1 in 0 ..< 360 {
for theta2 in 0 ..< 360 {
if( abs(Ca*r1*cos(theta1) - Ca*r2*cos(theta2)) < 0.01 && abs(Ca*r1*sin(theta1) - Ca*r2*sin(theta2)) < 0.01 ) {
print("point is: (", Ca*r1*cos(theta1), Ca*r1*sin(theta1),")")
}
}
}
根据您对匹配的容忍度,您不必围绕每个信号半径的圆周进行太多迭代来确定信号源位置的估计值。
我正在尝试根据从 4 个 Wi-Fi 接入点接收到的信号强度来估计位置。我测量了位于 100 平方米 (10x10) 方形房间每个角落的 4 个接入点的信号强度。我使用 Android phone 记录了已知位置 (x, y) = (9.5, 1.5) 的信号强度。现在我想检查在这种情况下多点定位方法的准确性。 使用 MATLAB,我应用了一个公式来使用信号强度计算距离。下面的 MATLAB 函数显示了公式的应用:
function [ d_vect ] = distance( RSS )
% Calculate distance from signal strength
result = (27.55 - (20 * log10(2400)) + abs(RSS)) / 20;
d_vect = power(10, result);
end
输入的RSS是在测试点(x,y) = (9.5, 1.5)测得的四个信号强度向量。 RSS 矢量如下所示:
RSS =
-57.6000
-60.4000
-44.7000
-54.4000
并且包含到每个接入点的所有估计距离的合成向量如下所示:
d_vect =
7.5386
10.4061
1.7072
5.2154
现在我想根据这些距离和接入点位置来估计我的位置,以便找到估计位置和已知位置(9.5,1.5)之间的误差。我想找到四个圆之间的交叉区域(为了估计一个位置),其中每个接入点是其中一个圆的中心,距离是圆的半径。
我想找到如图所示的灰色区域: http://www.biologycorner.com/resources/venn4.gif
所以基本上你需要与 4 个圆相交。可以有很多方法,有两种方法可以生成准确的交叉区域。
第一种方法是从一个圆开始,将它与第二个圆相交,然后将所得区域与第三个圆相交,依此类推。也就是说,在每一步你都知道当前的交叉区域,并且你将它与一个新的圆相交。相交区域将始终是一个由圆弧包围的区域,因此要将它与一个新圆相交,您可以沿着该区域的边界行走并检查每个边界弧是否与一个新圆相交。如果是,那么你只留下位于新圆内的圆弧部分,记住你应该继续从新圆开始的圆弧,并继续穿过边界,直到找到下一个交点。
另一种方法似乎会导致更糟糕的时间复杂度,但在您有 4 个圆圈的情况下,这并不重要,即找到两个圆圈的所有交点并仅选择那些感兴趣的点你,就在所有其他圈子里。这些点将是您所在区域的角,然后重建该区域就相当容易了。谷歌搜索了一下后,我什至找到了 live demo of this approach.
如果您想使用另一种方法来估计位置而不估计圆的交点,您可以使用 trilateration。给定一组距离测量值来估计位置是导航(例如 GPS)中的一种常用技术。
另外,如果你想要这个区域,因为你还需要估计位置的不确定性,我建议使用 least squares 解决三边测量问题,这将很容易地给你一个涉及的参数的估计和一个错误传播以产生位置的不确定性。
我找到了一个完美解决问题的答案。在这个link中有详细解释:
https://gis.stackexchange.com/questions/40660/trilateration-algorithm-for-n-amount-of-points
我也针对这个问题开发了一些MATLAB代码。开始了:
估计与接入点的距离:
function [ d_vect ] = distance( RSS )
result = (27.55 - (20 * log10(2400)) + abs(RSS)) / 20;
d_vect = power(10, result);
end
三边测量函数:
function [] = trilat( X, d, real1, real2 )
cla
circles(X(1), X(5), d(1), 'edgecolor', [0 0 0],'facecolor', 'none','linewidth',4); %AP1 - black
circles(X(2), X(6), d(2), 'edgecolor', [0 1 0],'facecolor', 'none','linewidth',4); %AP2 - green
circles(X(3), X(7), d(3), 'edgecolor', [0 1 1],'facecolor', 'none','linewidth',4); %AP3 - cyan
circles(X(4), X(8), d(4), 'edgecolor', [1 1 0],'facecolor', 'none','linewidth',4); %AP4 - yellow
axis([0 10 0 10])
hold on
tbl = table(X, d);
d = d.^2;
weights = d.^(-1);
weights = transpose(weights);
beta0 = [5, 5];
modelfun = @(b,X)(abs(b(1)-X(:,1)).^2+abs(b(2)-X(:,2)).^2).^(1/2);
mdl = fitnlm(tbl,modelfun,beta0, 'Weights', weights);
b = mdl.Coefficients{1:2,{'Estimate'}}
scatter(b(1), b(2), 70, [0 0 1], 'filled')
scatter(real1, real2, 70, [1 0 0], 'filled')
hold off
结束
其中,
X:具有 AP 坐标的矩阵
d: 距离估计向量
real1: 真实位置 x
real2: 实际位置 y
如果您有三组测量值(x,y)位置坐标和相应的信号强度。如:
m1 = (x1,y1,s1)
m2 = (x2,y2,s2)
m3 = (x3,y3,s3)
然后您可以计算每个点位置之间的距离:
d12 = Sqrt((x1 - x2)^2 + (y1 - y2)^2)
d13 = Sqrt((x1 - x3)^2 + (y1 - y3)^2)
d23 = Sqrt((x2 - x3)^2 + (y2 - y3)^2)
现在考虑每个信号强度测量值表示该信号的发射器,该信号来自远处的某个位置。该距离将是测量信号强度的位置的半径,因为此时人们不知道信号来自的方向。另外,信号越弱……半径越大。换句话说,信号强度测量将与半径成反比。信号强度越小,半径越大,反之亦然。所以,计算我们三个点的比例半径,虽然还不准确:
r1 = 1/s1
r2 = 1/s2
r3 = 1/s3
所以现在,在每一对点上,根据它们的距离分开,我们可以计算一个常数 (C),其中每个位置的半径将刚好相互接触。例如,对于点对 1 和 2:
Ca * r1 + Ca * r2 = d12
...求解常数 Ca:
Ca = d12 / (r1 + r2)
...我们也可以对其他两对执行此操作。
Cb = d13 / (r1 + r3)
Cc = d23 / (r2 + r3)
好吧...select 最大的 C 常数,Ca、Cb 或 Cc。然后,使用圆的参数方程找到坐标相交的位置。我会解释。
圆的参数方程为:
x = radius * Cos(theta)
y = radius * Sin(theta)
如果 Ca 是找到的最大常数,那么您将比较点 1 和 2,例如:
Ca * r1 * Cos(theta1) == Ca * r2 * Cos(theta2) &&
Ca * r1 * Sin(theta1) == Ca * r2 * Sin(theta2)
...从 0 度到 360 度迭代 theta1 和 theta2,对于两个圆。您可以编写如下代码:
for theta1 in 0 ..< 360 {
for theta2 in 0 ..< 360 {
if( abs(Ca*r1*cos(theta1) - Ca*r2*cos(theta2)) < 0.01 && abs(Ca*r1*sin(theta1) - Ca*r2*sin(theta2)) < 0.01 ) {
print("point is: (", Ca*r1*cos(theta1), Ca*r1*sin(theta1),")")
}
}
}
根据您对匹配的容忍度,您不必围绕每个信号半径的圆周进行太多迭代来确定信号源位置的估计值。