1

我正在尝试创建一个使用 Apple iBeacon 技术来确定自身当前室内位置的 android 智能手机应用程序。我已经设法获取所有可用的信标并通过 rssi 信号计算到它们的距离。

目前我面临的问题是,我找不到任何库或算法实现,该算法通过使用 3 个(或更多)固定点距离来计算 2D 中的估计位置,条件是这些距离不准确(这意味着,三个“三边圆”不相交于一点)。

如果有人可以用任何常见的编程语言(Java、C++、Python、PHP、Javascript 或其他)向我发布链接或实现,我将不胜感激。我已经在 stackoverflow 上阅读了很多关于该主题的内容,但找不到任何我能够在代码中转换的答案(只有一些使用矩阵和反转它们的数学方法,使用向量或类似的东西进行计算)。

编辑

我想了一个自己的方法,对我来说效果很好,但不是那么有效和科学。我遍历位置网格的每一米(或在我的示例中为 0.1 米),并通过比较该位置与所有信标的距离以及我计算的距离来计算该位置成为手机实际位置的可能性接收到 rssi 信号。

代码示例:

public Location trilaterate(ArrayList<Beacon> beacons, double maxX, double maxY)
{
    for (double x = 0; x <= maxX; x += .1)
    {
        for (double y = 0; y <= maxY; y += .1)
        {
            double currentLocationProbability = 0;
            for (Beacon beacon : beacons)
            {
                // distance difference between calculated distance to beacon transmitter
                // (rssi-calculated distance) and current location:
                // |sqrt(dX^2 + dY^2) - distanceToTransmitter|
                double distanceDifference = Math
                    .abs(Math.sqrt(Math.pow(beacon.getLocation().x - x, 2)
                                   + Math.pow(beacon.getLocation().y - y, 2))
                         - beacon.getCurrentDistanceToTransmitter());
                // weight the distance difference with the beacon calculated rssi-distance. The
                // smaller the calculated rssi-distance is, the more the distance difference
                // will be weighted (it is assumed, that nearer beacons measure the distance
                // more accurate)
                distanceDifference /= Math.pow(beacon.getCurrentDistanceToTransmitter(), 0.9);
                // sum up all weighted distance differences for every beacon in
                // "currentLocationProbability"
                currentLocationProbability += distanceDifference;
            }
            addToLocationMap(currentLocationProbability, x, y);
            // the previous line is my approach, I create a Set of Locations with the 5 most probable locations in it to estimate the accuracy of the measurement afterwards. If that is not necessary, a simple variable assignment for the most probable location would do the job also
        }
    }
    Location bestLocation = getLocationSet().first().location;
    bestLocation.accuracy = calculateLocationAccuracy();
    Log.w("TRILATERATION", "Location " + bestLocation + " best with accuracy "
                           + bestLocation.accuracy);
    return bestLocation;
}

当然,不利的一面是,我在 300 平方米的地板上有 30.000 个位置,我必须迭代并测量到我收到信号的每个信标的距离(如果是 5,我只进行 150.000 次计算以确定一个位置)。这很多 - 所以我会让这个问题开放,并希望有一些进一步的解决方案或对这个现有解决方案的良好改进,以使其更有效率。

当然,它不必是三边测量方法,就像这个问题的原始标题一样,拥有一个包含三个以上用于位置确定的信标的算法(多边测量)也是很好的。

4

3 回答 3

1

如果当前方法除了太慢之外还可以,那么您可以通过递归细分平面来加快速度。这有点像在 kd-tree 中找到最近的邻居。假设我们有一个轴对齐的盒子,并希望在盒子中找到近似的最佳解决方案。如果盒子足够小,则返回中心。

否则,将盒子分成两半,由 x 或 y 取决于哪一边更长。对于两半,计算解决方案质量的界限,如下所示。由于目标函数是相加的,因此对每个信标求和下限。信标的下限是圆到盒子的距离乘以比例因子。递归地在具有下限的孩子中找到最佳解决方案。只有当第一个孩子的最佳解决方案比另一个孩子的下限差时,才检查另一个孩子。

这里的大部分实现工作是框到圆的距离计算。由于盒子是轴对齐的,我们可以使用区间算术来确定从盒子点到圆心的精确距离范围。

PS:Math.hypot是计算二维欧几里得距离的好功能。

于 2014-09-17T19:57:33.127 回答
1

我不会考虑单个信标的置信水平,而是在您使用可用数据做出最佳猜测后尝试为您的结果分配整体置信水平。我认为唯一可用的指标(感知功率)不能很好地表明准确性。如果几何形状不佳或行为不端的信标,您可能会高度信任不良数据。假设您平等地信任所有信标,根据到信标的感知距离与计算点的对齐程度,得出一个整体置信水平可能更有意义。

我在下面写了一些 Python,它通过计算前两个信标的两个圆的交点,然后选择与第三个信标最匹配的点,根据提供的数据在 3 信标情况下得出最佳猜测。它旨在解决问题,而不是最终解决方案。如果信标不相交,它会稍微增加每个信标的半径,直到它们相遇或达到阈值。同样,它确保第三个信标在可设置的阈值内一致。对于 n 信标,我会选择 3 或 4 个最强信号并使用它们。有很多优化可以做,我认为这是一个试验性的问题,因为信标的笨拙性质。

import math

beacons = [[0.0,0.0,7.0],[0.0,10.0,7.0],[10.0,5.0,16.0]] # x, y, radius

def point_dist(x1,y1,x2,y2):
    x = x2-x1
    y = y2-y1
    return math.sqrt((x*x)+(y*y))

# determines two points of intersection for two circles [x,y,radius]
# returns None if the circles do not intersect
def circle_intersection(beacon1,beacon2):
    r1 = beacon1[2]
    r2 = beacon2[2]
    dist = point_dist(beacon1[0],beacon1[1],beacon2[0],beacon2[1])
    heron_root = (dist+r1+r2)*(-dist+r1+r2)*(dist-r1+r2)*(dist+r1-r2)
    if ( heron_root > 0 ):
        heron = 0.25*math.sqrt(heron_root)
        xbase = (0.5)*(beacon1[0]+beacon2[0]) + (0.5)*(beacon2[0]-beacon1[0])*(r1*r1-r2*r2)/(dist*dist)
        xdiff = 2*(beacon2[1]-beacon1[1])*heron/(dist*dist) 
        ybase = (0.5)*(beacon1[1]+beacon2[1]) + (0.5)*(beacon2[1]-beacon1[1])*(r1*r1-r2*r2)/(dist*dist)
        ydiff = 2*(beacon2[0]-beacon1[0])*heron/(dist*dist) 
        return (xbase+xdiff,ybase-ydiff),(xbase-xdiff,ybase+ydiff)
    else:
        # no intersection, need to pseudo-increase beacon power and try again
        return None

# find the two points of intersection between beacon0 and beacon1
# will use beacon2 to determine the better of the two points
failing = True
power_increases = 0
while failing and power_increases < 10:
    res = circle_intersection(beacons[0],beacons[1])
    if ( res ):
        intersection = res
    else:
        beacons[0][2] *= 1.001
        beacons[1][2] *= 1.001
        power_increases += 1
        continue
    failing = False

# make sure the best fit is within x% (10% of the total distance from the 3rd beacon in this case)
# otherwise the results are too far off
THRESHOLD = 0.1

if failing:
    print 'Bad Beacon Data (Beacon0 & Beacon1 don\'t intersection after many "power increases")'
else:
    # finding best point between beacon1 and beacon2
    dist1 = point_dist(beacons[2][0],beacons[2][1],intersection[0][0],intersection[0][1])
    dist2 = point_dist(beacons[2][0],beacons[2][1],intersection[1][0],intersection[1][1])
    if ( math.fabs(dist1-beacons[2][2]) < math.fabs(dist2-beacons[2][2]) ):
        best_point = intersection[0]
        best_dist = dist1
    else:
        best_point = intersection[1]
        best_dist = dist2
    best_dist_diff = math.fabs(best_dist-beacons[2][2])
    if best_dist_diff < THRESHOLD*best_dist:
        print best_point
    else:
        print 'Bad Beacon Data (Beacon2 distance to best point not within threshold)'

如果您想更加信任距离较近的信标,您可能需要计算两个最近的信标之间的交点,然后使用距离较远的信标进行平局。请记住,您对单个测量的“置信度”所做的几乎任何事情都充其量只是一种技巧。由于您将始终使用非常糟糕的数据,因此您肯定需要放宽 power_increases 限制和阈值百分比。

于 2014-09-17T20:10:08.613 回答
0

您有 3 个点:A(xA,yA,zA)、B(xB,yB,zB) 和 C(xC,yC,zC),它们分别位于目标点 G(xG, yG,zG)。假设 cA、cB 和 cC 是每个点的置信率 ( 0 < cX <= 1 )。基本上,您可能会采用非常接近 1 的值,例如 {0.95,0.97,0.99}。如果您不知道,请根据距离平均值尝试不同的系数。如果距离真的很大,你可能对它不是很自信。

这是我要做的方式:

var sum = (cA*dA) + (cB*dB) + (cC*dC);
dA = cA*dA/sum;
dB = cB*dB/sum;
dC = cC*dC/sum;

xG = (xA*dA) + (xB*dB) + (xC*dC);
yG = (yA*dA) + (yB*dB) + (yC*dC);
xG = (zA*dA) + (zB*dB) + (zC*dC);

基本的,不是很聪明,但可以完成一些简单的任务。

编辑

您可以在 [0,inf[ 中采用任何您想要的置信度系数,但恕我直言,限制在 [0,1] 是保持真实结果的好主意。

于 2014-09-16T07:38:20.110 回答