チュートリアル : HERE Positioning を使用してハイキングアプリを作成します。 アドベンチャー旅行のデジタル日記

ガルワール ヒマラヤ山脈のチャンドラシラ トレッキングへの道、AMSL 5000 m

アドベンチャー好きの方には、ハイキングやトレッキングの旅を記録して友人や家族に見せる興奮を覚えています。 カメラなどの従来の方法では、これらの体験を視覚的に記録できますが、撮影した正確な経路は記録されません。 このセクションで は、 HERE SDK for Android (Navigate Edition )を使用 して、大胆な旅程を記録し、視覚化します。

作成されたアプリを出発点として使用して、 HERE SDK の多くの機能を利用する独自のカスタマイズされたアプリケーションを作成できます。 さらに、 HERE SDK には、 GitHub にある既製のコードが付属しています。

ハイキングルートを HERE マップに表示したいので、歩数をカウントするのではなく、 GPS 信号の記録に重点を置いています。

次に、 HERE SDK を使用して HikingDiary アプリを作成してみましょう。

位置情報を取得して表示します

この GitHub レポジトリにある HERE SDK のコードスニペットを使用 すると、 HEREBackgroundPositioningServiceProvider をアプリに統合することで、コードを簡単にコピー&ペーストして位置を特定できます。HEREBackgroundPositioningServiceProviderは 、バックグラウンドであっても位置情報の更新をリッスンするために、バックグラウンドサービスリスナーとして HEREBackgroundPositioningService を使用します。

ハイキング中、私たちは通常、デバイスをポケットに入れてそこに置いておきます。 このため、ハイキングの追跡を続行するには、アプリのバックグラウンド更新をデフォルトで有効にします。

HEREBackgroundPositioningServiceは 、 HERE SDK が提供する位置情報エンジンを利用します。このエンジンは、 Android プラットフォームの位置情報を使用し、 GPS 、ネットワーク位置情報プロバイダ、その他のグローバル衛星ナビゲーションシステム( GNSS )受信機などのさまざまなソースから高精度の位置情報データを提供します。

次のステップで は、 LocationListener をメインクラスに統合して名前をHikingApp.java付け、その メインクラスのHEREBackgroundPositioningServiceProviderインスタンスをはじめにに作成することで、コピーしたHEREBackgroundPositioningServiceProviderを統合できます。

// A class to receive location events from the device.
public HEREBackgroundPositioningServiceProvider hereBackgroundPositioningServiceProvider;

// Sets listener to receive locations from HERE Positioning.
hereBackgroundPositioningServiceProvider = new HEREBackgroundPositioningServiceProvider(activity, locationListener);

...

// Receives location updates from LocationListener.
func onLocationUpdated(_ location: heresdk.Location) {
  ...
}

注 : LocationListener メインスレッドで呼び出さ れ、新しい場所が利用可能になるたびに呼び出されます。

サービスクラスHEREBackgroundPositioningServiceAndroidManifest.xml ファイルに追加することを忘れないでください。

  <service
    android:name="com.here.hikingdiary.backgroundpositioning.HEREBackgroundPositioningService"
    android:exported="false"/>

注 : 精度パラメーターを使用して、位置更新の精度を設定できます。 navigation この設定は、可能な限り高い精度です。

GitHubHikingAppクラスの最終実装を確認 できます。

必要な権限を追加

位置追跡では、ユーザーの居場所やアクティビティに関する機密情報が明らかになる可能性があるため、プライバシーに関する懸念が生じます。 このような問題に対処するために、多くのモバイルプラットフォームでは、位置情報データにアクセスする前にアプリが明示的にユーザーの同意を取得すること、および位置追跡の頻度と精度を制御するオプションを提供することが必要です。 アプリの開発者は、プライバシーに関する規制およびベストプラクティスに従って、位置情報データを責任を持って処理することが重要です。 したがって 、アプリでのLocationEngine の使用を開始する前に、必要な権限をアプリ AndroidManifest.xml のファイルに追加する必要があります。

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

作成された AndroidManifest.xml ファイルは GitHub にあります。

位置の正確さを処理します

位置情報を受信できるようになったので、位置情報の正確さを確認する必要があります。

onLocationUpdatedから受け取るオブジェクト Location は、特定の時間における世界中のユーザーの位置を記述したもので、真の地理座標の概算にすぎません。 静止していても、 GNSS 衛星は静止していませんが、宇宙を非常に高速に移動します。そのため、位置の推定値が移動する可能性があります。 たとえば、トレッキング中に瞑想したり食事をしたりする場合、推定位置は実際のロケーションから変化します。 このような状況では、自宅にいるときでも長距離を移動できるため、アプリは位置を更新しないでください。

次の図は、受信した GPS 信号の変動の問題を示しています。

図 : GPS 信号の視覚化。

ハイキング担当者は、ユーザーの位置を示します(移動中または移動していない)。 男性を囲む円は 、任意の時点T1 で horizontalAccuracyInMetersにより、半径が定義されている精度円です。 青い円は、いつでも T1 で水平 精度円の内側にある可能性が 68% 、 精度円の外側にある確率が 32% の場合の位置の例です。 たとえば、 horizontalAccuracyInMeters が10 メートルの場合、真の地理座標が半径 10 メートル以内にある可能性が 68% になります。 ハイキングの担当者が時間 T1 から T2 に移行すると 、値horizontalAccuracyInMeters が小さくなり、精度の低い円になります。 ただし、精度円内で真の地理座標が見つかる確率が高くなります。 このため、精度の低い円は大きい円よりも精度が高いと結論付けることができます。

単純な実装では、特定の精度しきい値未満のロケーションのみを受け入れることができます。

これにより、次に示すように、距離の計算が不正確になる可能性があります。

図 : 距離の計算に問題。

黒い線は GPS 信号に基づいて計算された距離で、青い線は実際の距離ですが、後ろにロープを伸ばして実際の経路を追跡しない限り、決定することは不可能です。

この問題の解決方法は?

位置フィルタリングアルゴリズムを作成します

上記の問題を解決するには、移動時にのみロケーションを受け入れるロケーションフィルタリングのアルゴリズムを作成する必要があります。 このために、新しい DistanceAccuracyLocationFilter クラスを作成 し、予定されている位置の水平精度および前回の位置見積もりまでの距離に基づいてフィルタリング戦略を提供します。

このためには、次の 2 種類のフィルターが必要です。

  1. DistanceFilter: 距離のしきい値に基づいて位置をフィルタリングします。
  2. AccuracyFilter: 推定位置の水平精度に基づいて位置をフィルタリングします。また、一定の精度の読み取り値のみが含まれます。 このフィルタを作成するに は、 HERE SDK によって提供されたLocationオブジェクトにあるhorizontalAccuracyInMetersプロパティを使用します。 推定水平精度がメートル単位で示され、真の地理座標がこの不確実性の半径内にあり、その確率は 68% であることが示されます ( 上の最初の図を参照 ) 。

このような距離フィルタをどのように実装できるかを見てみましょう。 まず 、プロパティdistanceThresholdInMeters を定義する必要があります。たとえば、 15 メートルとします。 推定された位置が、最後に受け入れられた位置からdistanceThresholdInMetersを超えている場合にのみ、 GPS 信号を受け入れます。 次の図は、計画したメカニズムの概念を示しています。

図 : 距離のしきい値の表示。

各円は、さまざまな精度の円を使用して、 1 つの位置の推定値を表します。 交差した円が距離のしきい値を下回ったため、廃棄されました。

DistanceFilterの上で、各 GPS 信号の精度も考慮する必要があります ( 上記を参照 ) 。 このため accuracyRadiusThresholdInMeters に、プロパティを定義します。 10 メートルとしましょう。 そのため、より大きい値の各 GPS 信号 accuracyRadiusThresholdInMeters がフィルタリングされます。 上の最初の図では、すべての青い GPS 信号が受け入れられ、赤い GPS 信号が廃棄されています。

これで、次の 2 つのフィルタメカニズムを使用して、アルゴリズムの実装に進む準備ができました。

public interface LocationFilterInterface {
  boolean checkIfLocationCanBeUsed(Location location);
}

public class DistanceAccuracyLocationFilter implements LocationFilterInterface {
  // These two parameters define if incoming location updates are considered to be good enough.
  // In the field, the GPS signal can be very unreliable, so we need to filter out inaccurate signals.
  private static final double ACCURACY_RADIUS_THRESHOLD_IN_METERS = 10.0;
  private static final double DISTANCE_THRESHOLD_IN_METERS = 15.0;
  private GeoCoordinates lastAcceptedGeoCoordinates;

  @Override
  public boolean checkIfLocationCanBeUsed(Location location) {
      if (isAccuracyGoodEnough(location) && isDistanceFarEnough(location)) {
          lastAcceptedGeoCoordinates = location.coordinates;
          return true;
      }
      return false;
  }

  // Checks if the accuracy of the received GPS signal is good enough.
  private boolean isAccuracyGoodEnough(Location location) {
      Double horizontalAccuracyInMeters = location.horizontalAccuracyInMeters;
      if (horizontalAccuracyInMeters == null) {
          return false;
      }

      // If the location lies within the radius of ACCURACY_RADIUS_THRESHOLD_IN_METERS then we accept it.
      if (horizontalAccuracyInMeters <= ACCURACY_RADIUS_THRESHOLD_IN_METERS) {
          return true;
      }
      return false;
  }

  // Checks if last accepted location is farther away than xx meters.
  // If it is, the new location will be accepted.
  // This way we can filter out signals that are caused by a non-moving user.
  private boolean isDistanceFarEnough(Location location) {
      if (lastAcceptedGeoCoordinates == null) {
          // We always accept the first location.
          lastAcceptedGeoCoordinates = location.coordinates;
          return true;
      }

      double distance = location.coordinates.distanceTo(lastAcceptedGeoCoordinates);
      if (distance >= DISTANCE_THRESHOLD_IN_METERS) {
          return true;
      }
      return false;
  }
}

DistanceAccuracyLocationFilter アルゴリズムは、 HERE SDK GitHub レポジトリにもあります。

ここで、受信位置信号のインスタンスのDistanceAccuracyLocationFilterを作成してフィルタリングし、マップ上の位置を更新できます。

private LocationFilterInterface locationFilter;

...

// Filter out undesired location signals.
locationFilter = new DistanceAccuracyLocationFilter();

...

public void onLocationUpdated(@NonNull Location location) {
    if (locationFilter.checkIfLocationCanBeUsed(location)) {
      // Use the location.
    }
}

LocationFilterInterface プロトコルを採用することで、独自の位置フィルタアルゴリズムを作成することもできます。 たとえば、次のようなバイパスフィルタを実装できます。

// The DefaultLocationFilter class implements the LocationFilterInterface and
// allows every location signal to pass in order to visualize the raw GPS signals on the map.
public class DefaultLocationFilter implements LocationFilterInterface {
    @Override
    public boolean checkIfLocationCanBeUsed(Location location) {
        return true;
    }
}

LocationFilterInterfaceでは、アプリのコア機能を変更せずに、ロケーションフィルタリングに異なるアルゴリズムを使用するようにアプリをカスタマイズできます。上記のフィルタリングアルゴリズムはできるだけシンプルに保たれており、ニーズに合わせて改善できます。

位置情報の更新を記録します

位置情報の更新が完了したら、次の手順で位置情報を記録します。 このため には、 HERE SDK GitHub の GPXTrackWriter コード スニペットを使用 して、 GPXTrack を作成します。 これ GPXTrackGPXDocument クラスで保存および読み込みできます。 GPXDocument にはすべての GPX トラックが含まれ、 GPX ファイル形式で保存されます。 このため、保存したファイルは、 GPX ファイル形式を理解している他のアプリケーションと簡単に共有できます。

GPX は、経由地、トラック、ルートなどの GPS データ交換の事実上の標準データ形式です。 GPX ファイルには、地理情報が XML 形式で含まれており、さまざまなソフトウェアプログラムや GPS デバイスで簡単に処理できます。

HERE SDK は、 GPX データの読み取り、表示、および操作をさまざまな方法で行うためのツールを提供することで、 GPX データの処理を支援します。

位置情報の更新を記録するには 、 GPX 操作を管理する GPXManager のインスタンスを作成します。

private GPXTrackWriter gpxTrackWriter = new GPXTrackWriter();
private GPXManager gpxManager;

// Create a GPXDocument file with named as myGPXDocument.
gpxManager = new GPXManager("myGPXDocument.gpx", context);

次に 、内部onLocationUpdated()メソッドにGPXTrack位置情報の更新を書き込みます。

// Add location updates to a GPX track.
gpxTrackWriter.onLocationUpdated(location)

最後に、ハイキングルートを保存するために、 GPX トラックを次のロケーションに保存する 1 行のコードを使用します GPXDocument

// Permanently store the trip on the device.
gpxManager.saveGPXTrack(gpxTrackWriter.getTrack());

旅程をロードするには、次を呼び出してください。

GPXTrack gpxTrack = gpxManager.getGPXTrack(index);
if (gpxTrack == null) {
    return;
}

注 : 複数のハイキングルート を1つのGPXDocumentに複数のGPXTrackとして記録して保存できます。

アプリをファイナライズします

アプリを完了するため に、マップ上に MapPolyline を使用して移動したパスを表示します。 の実装で MapPolylineは、 『開発者ガイド for the HERE SDK 』にあるマップアイテムガイドを使用します。 HikingApp.java クラスでも参照できます。

旅程中にポリラインを延長するため に、インスタンスgpxManager から最新の座標リストを取得します。これは、すでに最新の位置情報が含まれているためです。 このリストを使用して、 geoPolyline 既存 mapPolyline のインスタンスに設定した新しいインスタンスを作成できます。

// Update the polyline shape that shows the travelled path of the user.
mapPolyline.setGeometry(geoPolyline);

これにより、マップ ビューにすでに表示されているポリラインがただちに拡張されます。

このチュートリアルでは、アプリ開発プロセスのすべてのステップについて説明しているわけではありません。 より完全な写真を取得 するには、このはじめにガイドを参照してください。

GitHub で Android プロジェクト全体を検索 できます。

完成したアプリを以下に示します。

スクリーンショット : 衛星マップ スキーム搭載の HikingDiary アプリ。
スクリーンショット : HikingDiary アプリ屋外ラスタレイヤー付き

HERE SDK には、さまざまなマップスキームがあります。 デフォルトでは、アプリに SATELLITE マップ スキームが表示されます。 ただし、MapScheme を変更 して、別のマップ スキームに切り替えることができます。 使用可能な MapScheme のオプションの詳細については、HERE SDKの『 API リファレンス 』を参照してください。

また、アプリでは、メインビューの右上隅にあるスイッチをスライドさせて、マップビューの上に屋外ラスタレイヤーを作成できます。 これは、ハイトラインやより詳細な経路を示すため、ハイキングに適したサードパーティ製のラスターレイヤーです。 ここでは、 thunderforest.com の屋外マップを使用しています。 カスタムのラスタレイヤの詳細については、 『HERE SDK 開発者ガイド 』を参照してください。

次のステップ

この小さな HikingDiary アプリには、さまざまな改善方法があります。以下にいくつかのアイデアを示します。

  • 旅程に高さプロファイルを含めるには、GeoCoordinatesオブジェクトのaltitudeプロパティを使用します。
  • たとえば、 HERE SDK で TERRAIN は、より多くのマップスキームを統合して、丘の斜面を色分けするスキームを提供しています。
  • 旅程の合計期間と、休憩を取ったタイムスタンプを使用して、旅程を保存します。
  • 保存されている GPX ファイルのエクスポートオプションを含めて、他のアプリケーションと共有します。

GitHub のオープンソースプロジェクトとしてアプリをリリースしたので 、ご参加をお待ちしております。 バグ修正、新機能、全体的な改善を含むプルリクエストを自由に送信できます。

Happy Hiking!

」に一致する結果は 件です

    」に一致する結果はありません