1

Apples iBeacon テクノロジを使用して現在の屋内位置を特定する Android スマートフォン アプリケーションを作成しようとしています。利用可能なすべてのビーコンを取得し、rssi 信号を介してビーコンまでの距離を計算することができました。

現在、私はライブラリやアルゴリズムの実装を見つけることができないという問題に直面しています。これは、これらの距離が正確ではないという条件で固定点の 3 つ (またはそれ以上) の距離を使用して 2D で推定位置を計算します (これは、3 つの「三辺測量円」が 1 点で交わらないことを意味します)。

誰かが一般的なプログラミング言語 (Java、C++、Python、PHP、Javascript など) でのリンクまたは実装を投稿してくれれば、深く感謝します。私はすでにそのトピックについてstackoverflowで多くのことを読んでいますが、コードで変換できる答えを見つけることができませんでした(行列を使用した数学的アプローチとそれらの反転、ベクトルなどでの計算のみ)。

編集

私は独自のアプローチを考えました。これは私にとっては非常にうまく機能しますが、それほど効率的でも科学的でもありません。ロケーション グリッドを 1 メートル (または、この例では 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;
}

もちろん、これのマイナス面は、300m² のフロアに 30,000 の場所があることです。反復して、信号を受信したすべてのビーコンまでの距離を測定する必要がありました (それが 5 の場合、決定するためだけに 150,000 の計算を行います)。単一の場所)。それはたくさんあります-それで、質問を開いて、より効率的にするために、いくつかのさらなる解決策またはこの既存の解決策の優れた改善を期待します.

もちろん、この質問の元のタイトルのように、トライラテレーション アプローチである必要はありません。位置決定のために 3 つ以上のビーコンを含むアルゴリズム (マルチラテレーション) を使用することも良いことです。

4

3 に答える 3

1

現在のアプローチが遅すぎることを除けば問題ない場合は、平面を再帰的に細分化することで速度を上げることができます。これは、kd ツリーで最近傍を見つけるようなものです。軸に沿ったボックスが与えられ、そのボックス内で最適な近似解を見つけたいとします。ボックスが十分に小さい場合は、中心を返します。

それ以外の場合は、ボックスを x または y のどちらか長い側で半分に分割します。両方の半分について、次のように解の品質の境界を計算します。目的関数は加法的であるため、各ビーコンの下限を合計します。ビーコンの下限は、ボックスまでの円の距離にスケーリング係数を掛けたものです。下限を持つ子で最適な解を再帰的に見つけます。最初の子の最適解が他の子の下限よりも悪い場合にのみ、他の子を調べます。

ここでの実装作業のほとんどは、ボックスから円への距離の計算です。ボックスは軸に沿って配置されているため、間隔演算を使用して、ボックス ポイントから円の中心までの距離の正確な範囲を決定できます。

PS:Math.hypotは、2D ユークリッド距離を計算するための優れた関数です。

于 2014-09-17T19:57:33.127 に答える
1

個々のビーコンの信頼レベルを考慮に入れる代わりに、利用可能なデータを使用して可能な限り最善の推測を行った後、結果に全体的な信頼レベルを割り当てようとします. 利用可能な唯一の測定基準 (知覚力) が精度の良い指標になるとは思いません。ジオメトリが貧弱であったり、ビーコンが正しく動作していなかったりすると、貧弱なデータを非常に信頼することになります。すべてのビーコンを同等に信頼すると仮定して、ビーコンまでの知覚距離が計算された点とどれだけ一致しているかに基づいて、全体的な信頼レベルを考え出す方が適切な場合があります。

最初の 2 つのビーコンの円の交点の 2 つのポイントを計算し、3 つ目のビーコンに最もよく一致するポイントを選択することにより、3 ビーコンの場合に提供されたデータに基づいて最良の推測を行う 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)'

より近いビーコンをより信頼したい場合は、最も近い 2 つのビーコンの交点を計算し、より遠いビーコンを使用してタイブレークすることができます。個々の測定値の「信頼レベル」を使用して行うほとんどすべてのことは、せいぜいハックになることに注意してください。常に非常に悪いデータを扱うことになるため、power_increases の制限としきい値のパーセンテージを緩める必要があります。

于 2014-09-17T20:10:08.613 に答える
0

A(xA,yA,zA)、B(xB,yB,zB)、C(xC,yC,zC) の 3 つのポイントがあり、それぞれゴール ポイント G(xG, yG、zG)。cA、cB、および cC が各ポイントの信頼率 (0 < cX <= 1) であるとしましょう。基本的に、{0.95,0.97,0.99} のように 1 に非常に近いものを使用できます。わからない場合は、平均距離に応じて異なる係数を試してください。距離が非常に長い場合は、あまり自信がない可能性があります。

これが私がやる方法です:

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 に答える