1

わかりました。この質問に対する回答はすでにありますが、それに到達するまでに長い時間がかかったので、特に誰かが私に尋ねたので、関係のない質問の下で共有したいと思いました

GPS を使用して事前定義されたルート周辺のユーザーの位置を追跡するガイド付きウォーク用の Phonegap ベースのナビゲーション アプリを作成しました。私のルートには、ルート周辺の特定の地理的位置にトリガーが配置されており、現在の位置に基づいてユーザーに指示を出します。問題は、GPS の精度や信頼性があまり高くないことです。そのため、これらの場所の周りに約 20 メートルの「訪問半径」を許可したにもかかわらず、実際のテストでは、GPS 位置の更新が少し前に発生するため、これらのトリガーが見逃されることがありました。ユーザーは訪問半径に入り、少し後です。半径を大きくしようとしましたが、これはトリガーが早すぎてユーザーの現在の位置に関連していないことを意味していました。

では、「実際の」GPS データを使用して機能する方法でこれを解決するにはどうすればよいでしょうか?

4

1 に答える 1

5

私は地理空間計算のための数式の Movable Type によってこの素晴らしいページに出くわしました。さらに良いことに、数式のほとんどはすでに Javascriptで記述されており、これは私の Phonegap アプリにとって非常にクールでした。しかし、私の注意を引いたのは、2 点間のクロス トラック距離を計算するための次の式でした。私のアプリと実際の使用に関して言えば、これは、GPS の更新がターゲットの位置の半径を逃すほど頻繁ではない場合でも、ユーザーがターゲットにアクセスしたかどうかを、最新の位置とその前身。

EDIT 24/04/15:constrainedCrossTrackDistance関数のバグを修正したので、それを使用している人は誰でも実装をこの回答のも​​のに更新する必要があります。

JS ライブラリにはこの数式が含まれていなかったので、Movable Type ライブラリを拡張して実装しました。

/**
 * Calculates distance of a point from a great-circle path (also called cross-track distance or cross-track error)
 * 
 * Formula: dxt = asin(sin(d13/R)*sin(b13-b12)) * R
 * where 
 *  d13 is distance from start point to third point
 *  b13 is (initial) bearing from start point to third point
 *  b12 is (initial) bearing from start point to end point
 *  R is the earth's radius
 * 
 * @param {LatLon} startPoint - Point denoting the start of the great-circle path
 * @param {LatLon} endPoint - Point denoting the end of the great-circle path
 * @param {Number} [precision=4] - no of significant digits to use for calculations and returned value
 * @return {Number} - distance in km from third point to great-circle path
 */
LatLon.prototype.crossTrackDistance = function(startPoint, endPoint, precision){
    var R = this._radius;
    var d13 = startPoint.distanceTo(this, 10);
    var b13 = startPoint.bearingTo(this).toRad();
    var b12 = startPoint.bearingTo(endPoint).toRad();
    var d = Math.asin(Math.sin(d13/R)*Math.sin(b13-b12)) * R;
    return d.toPrecisionFixed(precision);
}

ただし、実際のテストでは、これがうまくいかないことが再び示されました。問題は、この関数が 2 つの端点と半径によって形成されるバウンディング ボックスを考慮していなかったため、誤検知が発生していたことです。これにより、クロストラック距離をその境界ボックス内に制限する関数をさらに追加することになりました。

/**
 * Calculates distance of a point from a great-circle path if the point is within the bounding box defined by the path.
 * Otherwise, it returns the distance from the point to the closest end of the great-circle path.
 * 
 * @param {LatLon} startPoint - Point denoting the start of the great-circle path
 * @param {LatLon} endPoint - Point denoting the end of the great-circle path
 * @param {Number} [precision=4] - no of significant digits to use for calculations and returned value
 * @return {Number} - distance in km from third point to great-circle path
 */
LatLon.prototype.constrainedCrossTrackDistance = function(startPoint, endPoint, precision){

  var bAB = startPoint.bearingTo(endPoint);
  var bAB_plus_90 = Geo.adjustBearing(bAB, 90);
  var bAB_minus_90 = Geo.adjustBearing(bAB, -90);
  var bAC = startPoint.bearingTo(this);
  var bBC = endPoint.bearingTo(this);
  var dAC = startPoint.distanceTo(this, 10);
  var dBC = endPoint.distanceTo(this, 10);
  if(Geo.differenceInBearings(bAC, bBC) > 90 && ((bBC > bAB_plus_90 && bAC < bAB_plus_90) || (bAC > bAB_minus_90 && bBC < bAB_minus_90))){
    return Math.abs(this.crossTrackDistance(startPoint, endPoint, precision));
  }else if((bBC < bAB_plus_90 && bAC < bAB_plus_90) || (bBC > bAB_minus_90 && bAC > bAB_minus_90)){
    return Math.abs(dBC);
  }else if((bBC > bAB_plus_90 && bAC > bAB_plus_90) || (bBC < bAB_minus_90 && bAC < bAB_minus_90)){
    return Math.abs(dAC);
  }else{
    return (Math.abs(dBC) < Math.abs(dAC) ? Math.abs(dBC) : Math.abs(dAC));
  }
}

これを使用して、実際のシナリオでターゲット位置が訪問されたかどうかを判断できます。

// Calculate if target location visited
    if(
        currentPos.distanceTo(targetPos)*1000 < tolerance ||
        (prevPos && Math.abs(targetPos.constrainedCrossTrackDistance(prevPos, currentPos)*1000) < tolerance)
    ){
        visited = true;
    }else{
        visited = false;
    }

これはユースケースを示すフィドルです

これを思いつくのに長い時間と多くのテストが必要だったので、他の人の助けになることを願っています:-)

于 2013-06-10T19:26:19.830 に答える