具有不准确距离数据的Multiliteration实现

时间:2014-09-15 15:52:55

标签: algorithm localization ibeacon indoor-positioning-system trilateration

我正在尝试创建一个Android智能手机应用程序,它使用Apples iBeacon技术来确定自身的当前室内位置。我已经设法获得所有可用的信标并通过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计算仅用于确定单个位置)。这是很多 - 所以我会打开这个问题并希望得到一些进一步的解决方案或对现有解决方案的改进,以提高效率。

当然它不是一个Trilateration方法,就像这个问题的原始标题一样,拥有一个包含三个以上信标的算法也可以用于位置确定(Multilateration)。

3 个答案:

答案 0 :(得分:1)

如果当前的方法很好,除了太慢,那么你可以通过递归细分平面来加速它。这有点像在kd树中找到最近的邻居。假设我们给出了一个轴对齐框,并希望在框中找到近似最佳解决方案。如果盒子足够小,那么返回中心。

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

这里的大多数实现工作都是盒到圆距离计算。由于方框是轴对齐的,我们可以使用interval arithmetic来确定从方框点到圆心的精确距离范围。

P.S。:Math.hypot是计算2D欧几里德距离的一个很好的函数。

答案 1 :(得分: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)'

如果你想更多地信任更近的信标,你可能想要计算两个最接近的信标之间的交叉点,然后使用更远的信标来打破平局。请记住,几乎所有你做的事情&#34;信心水平&#34;对于个人测量而言,最好是黑客攻击。由于您将始终处理非常糟糕的数据,因此您最终需要放松power_increases限制和阈值百分比。

答案 2 :(得分:0)

你有3个点:A(xA,yA,zA),B(xB,yB,zB)和C(xC,yC,zC),它们分别大约是你的目标点G的dA,dB和dC (XG,YG,ZG)。 假设cA,cB和cC是每个点的置信度(0

以下是我的方式:

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]中限制你想要的任何自信心,以保持一个真实的结果。