【问题标题】:Multiliteration implementation with inaccurate distance data具有不准确距离数据的多文本实现
【发布时间】:2014-09-15 15:52:54
【问题描述】:

我正在尝试创建一个 Android 智能手机应用程序,该应用程序使用 Apple 的 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 次计算仅用于确定单个位置)。这很多 - 所以我会让这个问题开放,并希望有一些进一步的解决方案或对现有解决方案进行良好改进,以使其更有效率。

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

【问题讨论】:

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


    【解决方案1】:

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

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

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

    P.S.:Math.hypot 是一个很好的计算二维欧几里得距离的函数。

    【讨论】:

      【解决方案2】:

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

      我在下面写了一些 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 限制和阈值百分比。

      【讨论】:

        【解决方案3】:

        您有 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] 是保持真实结果的好主意。

        【讨论】:

        • 我需要一段时间来了解您的方法。我认为问题在于,它试图在 3 个给定点中找到一个点。例如,如果我有以下点、范围设置(全部置信度为 1.0,在此示例中测量是精确的): [{x: 0, y: 0, z: 0, d: 3}, {x: 1 , y: 3, z: 0, d: 1}, {x: 4, y: 0, z: 0, d: 5}] 并且目标点在 {x: 0, y: 3, z: 0 }。不幸的是,您的算法没有给出任何接近的点: {x: 2.3333333333333335, y: 0.3333333333333333, z: 0} 是计算的结果。您有任何改进的想法还是我错过了什么?
        猜你喜欢
        • 2013-10-31
        • 1970-01-01
        • 2014-02-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多