web-dev-qa-db-ja.com

モバイルが実際に移動した距離を計算する

モバイル(iOSおよびAndroid)の実際の移動距離を計算したい。 Google Map APIを使用すると、2つの座標間の最適なルート距離を見つけることができます。しかし、距離を計算したいのですが、実際のモバイル(車内)の経路がカバーされています。

私が知った1つのアルゴは、x秒後に座標を保存し、5または10秒後に言って、連続した座標間の距離を計算すると、合計が合計距離を与えます。

私はその解決策のより良いアプローチについて議論したい、より良い解決策はありますか?

編集:Nike実行アプリやUberのようなアプリはどのように機能しますか?

35
Haris

------------------[〜#〜] update [〜#〜]--- -------------------

あなたの質問には2つの大きなポイントがあります。

1)電話座標を取得します(この応答の最初の部分で処理されています)

2)この2つの座標間の距離を計算する

私見、計算はWebサービスによって実行できます。2つの座標間の距離のみに基づく計算は、本当に間違った結果につながる可能性があります。

このようなWebサービスの例を次に示します https://graphhopper.com/#directions-api

デモアプリ: https://graphhopper.com/api/1/examples/

(このツールの多くと同様に)トラフィックフローに基づいているため、間違った結果をもたらす可能性があるため、座標の順序に注意する必要があります。

2つのポイントが正しい順序である例: enter image description here

これは良い結果をもたらします

ただし、同じ座標で間違った順序を指定した場合 enter image description here

同じ座標の場合、極端に異なる結果になる可能性があります。

したがって、座標ABCD(年代順)については、以下を行う必要があります。

A-> B B-> C C-> D

Graphhopperはオフライン距離計算を実行できるようです

IOSおよびAndroidのライブラリは次のとおりです。

https://github.com/graphhopper/graphhopper-ios/

https://github.com/graphhopper/graphhopper/tree/master/Android

----------------------------------------- ----------

アプリの動作を定義する必要があります。前景か背景か?

他の応答で述べたように、X秒ごとにユーザーの位置を取得する必要があります。次に、距離を計算します。

iOSの場合:

  1. このWebサイトの情報を使用できます。 http://mobileoop.com/

アプリがバックグラウンドにある場合のiOSでのユーザーの位置の追跡について説明します。

  1. Githubは次のとおりです。 https://github.com/voyage11/Location

次に、ポイントのおかげで変換する必要があります

CLLocationDistance distance = [aCLLocationA distanceFromLocation:aCLLocationB];

これも確認できます(Apple doc) https://developer.Apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.htmlから)

ロケーションマネージャーのpausesLocationUpdatesAutomaticallyプロパティがYESに設定されていることを確認します。このプロパティがYESに設定されている場合、ユーザーが移動する可能性が低い場合など、そうすることが理にかなっている場合はいつでも、コアロケーションはロケーション更新を一時停止します(ロケーションハードウェアの電源を切ります)。 (コアロケーションも、ロケーション修正を取得できない場合、更新を一時停止します。)

ロケーションマネージャーのactivityTypeプロパティに適切な値を割り当てます。このプロパティの値は、ロケーションマネージャーがロケーションの更新を一時停止しても安全かどうかを判断するのに役立ちます。ターンバイターンの自動車ナビゲーションを提供するアプリの場合、プロパティをCLActivityTypeAutomotiveNavigationに設定すると、ロケーションマネージャーは、ユーザーが一定の時間にわたって大きな距離を移動しない場合にのみイベントを一時停止します。

CLActivityTypeAutomotiveNavigation道路上の位置を確実に取得します。

Androidの場合:

  1. このプロジェクトを使用できます: https://github.com/quentin7b/Android-location-tracker

TrackerSettingsオブジェクトのおかげで、ユーザーの位置を簡単に取得できます。

TrackerSettings settings =
        new TrackerSettings()
            .setUseGPS(true)
            .setUseNetwork(true)
            .setUsePassive(true)
            .setTimeBetweenUpdates(30 * 60 * 1000)
            .setMetersBetweenUpdates(100);
  1. Androidで2つのポイント間の距離を見つけるには、次を確認します。 2つのジオポイント間の距離を取得

OS両方

X秒ごとに取得される位置に基づいて、位置データを取得する間隔を短縮して精度を向上させる必要があります。

道路のコンテキストで距離を計算する場合は、ロケーションマネージャーをナビゲーションモードに設定します。このモードでは、道路上の座標が得られます。

最後に

距離計算の精度を向上させる場合は、Google APIを使用できます。 https://developers.google.com/maps/documentation/distance-matrix/intro

正しいmodeパラメーターを設定することにより:

オプションのパラメーター

mode(デフォルトは運転モード)—距離を計算するときに使用する輸送モードを指定します。有効な値とその他のリクエストの詳細は、このドキュメントの旅行モードのセクションで指定されています。

20
Alban

私はAndoriodで似たようなことに取り組んでいますが、プリンシパルはiOSでも同じです:

  1. 各GPSサンプルについて、その精度を確認します。しきい値(たとえば20メートル)を超えている場合は無視します。
  2. モバイルデバイスが静止している場合でも、精度に応じてGPSサンプルが異なると、異なる場所が得られることに注意してください。信号機で長時間静止している車は、数十メートル進んだことを示すため、モバイルが静止しているかどうかを検出するメソッドを追加します。加速度計を読み取ることでこれを実装しました-2つの読み取り値の差があるしきい値よりも大きい場合、デバイスは移動しています。小さすぎる場合-GPSを無視します。
  3. 車で使用する場合は、新しい読み取り値があればいつでもGPSを読み取ることができます(Android onLocationChangedメソッドを使用)。実行に使用する場合/ウォーキングでは、速度が遅いことを考慮してください-2つの連続した測定値は比較的近い値になりますが、GPSの精度により、それらの間の距離は非常に長くなります。または、それらのいくつかを無視することによって(つまり、10回ごとの読み取りのみを考慮に入れる)。
  4. Haversine式 を使用して、2つの連続した読み取り値間の距離を計算します。 Androidでは、Location.distanceTo()メソッドで実行できます。

車の走行距離計でテストし、加速度計のしきい値を調整する必要があります。

9
TDG

次の戦略を組み合わせることで、より高い精度を実現できます。

  1. 他の回答で述べたように、GPSを使用してX秒ごとにモバイルの位置を保存します(たとえば10秒)ポイント間の連続時間を測定します。

  2. また、ユーザーがクイックターンを行うときは、磁気センサー値を使用してそれを必ず読み取ってください。そのような場合は、「位置記憶間のタイミング」を1- 2秒(正確さのために必要になります)

  3. 最後のステップとして、地図データ(Googleマップなど)を使用して、適切に追跡されていることを確認します(道路上にある場合)。

そして、すべての値を合計して正確な距離を取得します。

追伸Android(またはiOS)での実装についてはよく分からないので、戦略についてのみ情報を提供しました。

お役に立てれば :)

7
Snazzy Sanoj

4年前、Landsurvayorというアプリを作成しました。このアプリは、Googleマップに描かれた2つの地理的ポイントの実際の距離を計算します。私はそれがあなたに役立つかもしれないかどうかは知りませんが、2つの地理的なポイント間の実際の距離を計算するHaversineの式と呼ばれる式がありますあなたはそれを試してみて、それがあなたにとって役に立つかどうかを見るかもしれません。 Haversine数式のサンプルコードは次のとおりです。

public double CalculationByDistance(double initialLat, double initialLong,
                            double finalLat, double finalLong){
int R = 6371; // km
double dLat = toRadians(finalLat-initialLat);
double dLon = toRadians(finalLong-initialLong);
lat1 = toRadians(lat1);
lat2 = toRadians(lat2);

double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2); 
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
return R * c;
}

public double toRadians(deg) {
  return deg * (Math.PI/180)
}

Haversineフォーミュラの詳細: https://en.wikipedia.org/wiki/Haversine_formula

2つの緯度経度間の距離を計算する別の簡単なAndroid SDKビルトインアプローチ:

Location locationA = new Location("point A");     
locationA.setLatitude(latA); 
locationA.setLongitude(lngA);
Location locationB = new Location("point B");
locationB.setLatitude(latB); 
LocationB.setLongitude(lngB);
distance = locationA.distanceTo(locationB) ;

それがあなたの助けになることを願っています。

6
Gagan Singh

正確な(またはほぼ正確な)距離情報を探している場合は、たどる経路を追跡する必要があります。つまり、数秒ごとに座標を確認する必要があります(予想される移動速度に応じて)。各セグメントを計算し、現在の移動距離を保存するだけで古い座標を破棄することにより、スペースを節約できます。

3
Calteran

GPS座標の使用に関する1つの問題は、それらが(明らかに)正確ではないことです。直線で移動している場合、GPS座標はジグザグの経路で移動していることを示している可能性があるため、実際の距離よりも大きな移動距離を返します。 GPSの精度が良好であっても、このエラーは重大な場合があります。より少ない座標を使用すると、より正確な計算が行われる場合と行われない場合があります。

必要なのは、必要な精度を十分に考慮して、プロットされたGPSパスを滑らかにする方法です(これもトレードオフです)。

私の最初の考えは、ポイントをグループに分割し、各グループに線分を当てはめることです(「線形回帰」を調べてください)。次に、連続する各ラインペアが重複する場所を見つけて、各ラインセグメントを定義します。次に、線分の長さを合計します。

セグメントをカーブフィットすることもできますが、数学的にははるかに強力であり、より良い結果が得られない可能性があります(使用するカーブ式は?)。私が知らないより良い数学的な方法があるかもしれません。

お役に立てれば。

3
John Cook

GPSを使用して両方の場所の緯度経度を取得し、両方を取得した後、メソッドの下にパスします。距離はkm単位で返されます

public static double getDistanceFromLatLonInKm(double lat1, double lon1,
        double lat2, double lon2) {



    double R = 6371; // Radius of the earth in km
    double dLat = deg2rad(lat2 - lat1); // deg2rad below
    double dLon = deg2rad(lon2 - lon1);
    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
            + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
            * Math.sin(dLon / 2) * Math.sin(dLon / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double d = R * c; // Distance in km


    return d;

}

public static double deg2rad(double deg) {
    return deg * (Math.PI / 180);
}

}

3
Jotiram Chavan

精度が重要な場合は、加速度計とジャイロスコープのデータを使用できます。シンプルな映画のタスクを解決するための非常にシンプルな公式を見つけることができるので、グローバル軸でaccを取得できます。積分を2回使用する必要があります(最初に速度を取得し、位置を取得する)。別の視点を示すためだけに。

3
muminers

Android :: Androidでの歩行中の距離の計算方法

これを行うにはさまざまな方法があります。

1.GPS:X秒(10秒など)ごとに2ポイント間のGPS距離を追加し続けます。 Check Android Location.distanceToまたはdistanceBetween。MyTracksアプリをチェックしてください。オープンソースです。GPSは屋内では利用できず、ユーザーが頻繁に方向を変えている場合はエラーが発生します。 )2.加速度計:加速度計を使用したステップ検出用のコード/ライブラリを探します。距離は加速度の二重積分から生じるため、ここでエラーが急速に増加する場合があります。3.ステップ検出器:Nexus 5に組み込まれています。これはハードウェアベースの計算であり、バッテリーの消費は少なくなりますが、現在のほとんどの携帯電話では利用できません。

2番目のオプションはあなたが提案したものと非常に似ているようで、iOSとAndroidはコードと機能を延期し、それを達成するための最良の方法は保存することですcurrentLocationおよびpreviousLocationwhileループで。sleep()そして、移動距離に応じてループ全体を合計します。より大きな問題は、このアプリは距離サマー化アプリですか?それは内部の小さな機能ですか?距離の計算をいつ停止するかをどのように決定しますか?

3
Daniel Netzer

X秒ごとにポイントをログに記録し(2〜3か?)、記録するすべてのポイントに対して以下の距離式を使用します。

Distance = sqrt((x2−x1)^2+(y2−y1)^2)

それらをすべて合計すると、距離が得られます

2
lawonga