ナビゲーションアプリを作成する
ガイダンスを開始するには、2つの方法があります。ヘッドレス Navigator を使用するか、VisualNavigator を使用します。どちらの場合もインターフェースは同じですが、Navigator では VisualNavigator のサブセットが提供されるのに対して、VisualNavigator では上部にビジュアル レンダリング アシスタンスが表示され、個別の Location の更新間のスムーズな補間などの機能が提供されます。
以下では、VisualNavigator を使用します。
ナビゲーション アプリの基本的な原理は次のとおりです。
Routeを作成します。トラッキング モードを開始しない限り、追随するルートがないとルート案内を開始できません。VisualNavigatorインスタンスを作成してレンダリングを開始します (独自のガイダンス ビューをレンダリングする場合はNavigatorインスタンスを作成します)。RouteをVisualNavigatorに設定します。トラッキング モードを開始する場合を除きます。VisualNavigatorに位置情報の更新がフィードされます。位置情報データがないと、ルート上のルート進行状況を検出できません。また、道路標識などの今後の道路イベントのイベントは、ユーザーの位置を把握しないと利用できません。位置をシミュレートすることも、実際の位置情報の更新をフィードすることもできます。
GitHub の NavigationQuickStart アプリは、ナビゲーション アプリの基本原則を示しています。
ナビゲーション アプリの基本スケルトンは次のようになります。
private void startGuidance(Route route) {
try {
// Without a route set, this starts tracking mode.
visualNavigator = new VisualNavigator();
} catch (InstantiationErrorException e) {
throw new RuntimeException("Initialization of VisualNavigator failed: " + e.error.name());
}
// This enables a navigation view including a rendered navigation arrow.
visualNavigator.startRendering(mapView);
// Hook in one of the many listeners. Here we set up a listener to get instructions on the maneuvers to take while driving.
// For more details, please check the "Navigation" example app and the Developer Guide.
visualNavigator.setEventTextListener(eventText -> {
Log.d("ManeuverNotifications", eventText.text);
});
// Set a route to follow. This leaves tracking mode.
visualNavigator.setRoute(route);
// VisualNavigator acts as LocationListener to receive location updates directly from a location provider.
// Any progress along the route is a result of getting a new location fed into the VisualNavigator.
setupLocationSource(visualNavigator, route);
}
private fun startGuidance(route: Route?) {
try {
// Without a route set, this starts tracking mode.
visualNavigator = VisualNavigator()
} catch (e: InstantiationErrorException) {
throw RuntimeException("Initialization of VisualNavigator failed: " + e.error.name)
}
// This enables a navigation view including a rendered navigation arrow.
visualNavigator!!.startRendering(mapView!!)
// Hook in one of the many listeners. Here we set up a listener to get instructions on the maneuvers to take while driving.
// For more details, please check the "Navigation" example app and the Developer's Guide.
visualNavigator!!.eventTextListener = EventTextListener { eventText: EventText -> Log.d("Maneuver text", eventText.text) }
// Set a route to follow. This leaves tracking mode.
visualNavigator!!.route = route
// VisualNavigator acts as LocationListener to receive location updates directly from a location provider.
// Any progress along the route is a result of getting a new location fed into the VisualNavigator.
setupLocationSource(visualNavigator!!, route)
}
開始するには、LocationSimulator を使用して、シミュレーションされたソースを選択します。このクラスは、ルートの道路形状に基づいて位置イベントを提供します。
private void setupLocationSource(LocationListener locationListener, Route route) {
try {
// Provides fake GPS signals based on the route geometry.
locationSimulator = new LocationSimulator(route, new LocationSimulatorOptions());
} catch (InstantiationErrorException e) {
throw new RuntimeException("Initialization of LocationSimulator failed: " + e.error.name());
}
locationSimulator.setListener(locationListener);
locationSimulator.start();
}
private fun setupLocationSource(locationListener: LocationListener, route: Route?) {
try {
// Provides fake GPS signals based on the route geometry.
locationSimulator = LocationSimulator(route!!, LocationSimulatorOptions())
} catch (e: InstantiationErrorException) {
throw RuntimeException("Initialization of LocationSimulator failed: " + e.error.name)
}
locationSimulator!!.listener = locationListener
locationSimulator!!.start()
}
上記のコード スニペットは、Route から取得された、シミュレートされた Location イベントを使用してシミュレートされたルート案内を開始するために必要なすべてのコードを示しています。これは VisualNavigator インスタンスを使用しているため、stopRendering() が呼び出されるまで、HERE SDK がレンダリング部分を引き継ぎます。
これで、必要に応じてイベントのリスナーまたは警告をVisualNavigatorインスタンスに追加できるようになりました。リスナーの添付に特別なことは何もありません。基本的には、関連するナビゲーションセクションに示されているコード スニペットを使用できます。
今後は、運転操作などのイベントデータの可視化に役立つ、より使いやすいUI構成要素を提供する予定です。
以下では、柔軟な位置情報プロバイダーを構築するために推奨される手順を詳しく説明します。また、開発中にテストするためのシミュレーター クラスを作成する方法についても説明し、ルート再生をカスタマイズするためのさまざまなオプションを提示します。
位置情報プロバイダーを実装する
位置情報プロバイダーは Location インスタンスを VisualNavigator に提供する必要があります。位置情報データは任意のソースからフィードできます。以下の例では、デバイスからのネイティブな位置情報データとテスト運転用のシミュレーション位置情報データを切り替えることができる実装を使用します。
先に説明したように、VisualNavigator は LocationListener インターフェースに準じているため、onLocationUpdated() を呼び出すクラスのリスナーとして使用できます。
位置情報データのソースとして、「Positioning」セクションで示したコードに基づいた HEREPositioningProvider を使用します。
注ナビゲーションでは
LocationEngineの起動時にLocationAccuracy.NAVIGATIONを使用することをお勧めします。これにより、ターン・バイ・ターンナビ中に最適な結果が保証されます。
イベントを配信するには、herePositioningProvider を起動する必要があります。
// Call this to start getting locations from a device's sensor.
herePositioningProvider.startLocating(visualNavigator, LocationAccuracy.NAVIGATION);
// Call this to start getting locations from a device's sensor.
herePositioningProvider.startLocating(visualNavigator, LocationAccuracy.NAVIGATION)
必要とされる HERE SDK Location タイプには、現在の地理座標および VisualNavigator によって消費されるその他の情報とともに方位と速度の情報が含まれています。提供されたデータが正確で完全であるほど、全体的なナビゲーション エクスペリエンスはより正確になります。
Location オブジェクトから取得される bearing 値によって移動の方向が決まり、その方向に合わせて回転する LocationIndicator アセットによって移動の方向が示されます。ユーザーが移動していない場合は、新しい方位の値が設定されるまで最後の回転が保持されます。Location データのソースにより、この値の正確性には差があります。
内部的には、Locationのtimestampは、ユーザーがトンネルを走行しているのか、あるいは単に信号が失われているかなどを評価するために使用されます。
位置情報プロバイダーのリファレンス実装は、GitHubにJava版およびKotlin版の両方があります。
位置情報シミュレーターを設定する
開発中は、テストのためにルート上で予想される進行状況を再生するのに役立つ可能性があります。LocationSimulator は元のルートの座標から取得された連続した位置信号を提供します。
以下では、LocationSimulator を代替プロバイダーとして統合し、実際の位置情報の更新とシミュレートされた位置を切り替えられるようにします。
import com.here.sdk.core.LocationListener;
import com.here.sdk.core.errors.InstantiationErrorException;
import com.here.sdk.navigation.LocationSimulator;
import com.here.sdk.navigation.LocationSimulatorOptions;
import com.here.sdk.routing.Route;
// A class that provides simulated location updates along a given route.
// The frequency of the provided updates can be set via LocationSimulatorOptions.
public class HEREPositioningSimulator {
private LocationSimulator locationSimulator;
// Starts route playback.
public void startLocating(LocationListener locationListener, Route route) {
if (locationSimulator != null) {
locationSimulator.stop();
}
locationSimulator = createLocationSimulator(locationListener, route);
locationSimulator.start();
}
public void stopLocating() {
if (locationSimulator != null) {
locationSimulator.stop();
locationSimulator = null;
}
}
// Provides fake GPS signals based on the route geometry.
private LocationSimulator createLocationSimulator(LocationListener locationListener, Route route) {
LocationSimulatorOptions locationSimulatorOptions = new LocationSimulatorOptions();
locationSimulatorOptions.speedFactor = 2;
locationSimulatorOptions.notificationInterval = Duration.ofMillis(500);
LocationSimulator locationSimulator;
try {
locationSimulator = new LocationSimulator(route, locationSimulatorOptions);
} catch (InstantiationErrorException e) {
throw new RuntimeException("Initialization of LocationSimulator failed: " + e.error.name());
}
locationSimulator.setListener(locationListener);
return locationSimulator;
}
}
import com.here.sdk.core.LocationListener
import com.here.sdk.core.errors.InstantiationErrorException
import com.here.sdk.navigation.LocationSimulator
import com.here.sdk.navigation.LocationSimulatorOptions
import com.here.sdk.routing.Route
import com.here.time.Duration
// A class that provides simulated location updates along a given route.
// The frequency of the provided updates can be set via LocationSimulatorOptions.
class HEREPositioningSimulator {
private var locationSimulator: LocationSimulator? = null
// Starts route playback.
fun startLocating(locationListener: LocationListener, route: Route) {
if (locationSimulator != null) {
locationSimulator!!.stop()
}
locationSimulator = createLocationSimulator(locationListener, route)
locationSimulator!!.start()
}
fun stopLocating() {
if (locationSimulator != null) {
locationSimulator!!.stop()
locationSimulator = null
}
}
// Provides fake GPS signals based on the route geometry.
private fun createLocationSimulator(
locationListener: LocationListener,
route: Route
): LocationSimulator {
val locationSimulatorOptions = LocationSimulatorOptions()
locationSimulatorOptions.speedFactor = 2.0
locationSimulatorOptions.notificationInterval = Duration.ofMillis(500)
val locationSimulator: LocationSimulator
try {
locationSimulator = LocationSimulator(route, locationSimulatorOptions)
} catch (e: InstantiationErrorException) {
throw RuntimeException("Initialization of LocationSimulator failed: " + e.error.name)
}
locationSimulator.listener = locationListener
return locationSimulator
}
}
さらに、LocationSimulatorOptions を設定することで、現在のシミュレートされた位置がどのくらい速く移動するかを指定できます。デフォルトでは notificationInterval が 1、speedFactor が 1.0 で、これは、交通状況に関連する制約を考慮せずにユーザーが各ルート セグメントを通常運転または歩行する平均速度に相当します。デフォルトの速度は、道路形状、道路条件、その他の統計データによって異なりますが、現在の制限速度を超えることはありません。値が 1.0 を超えると、比例して速度が増加します。指定の時間間隔に十分な座標がルートに含まれていない場合、追加の位置イベントが VisualNavigator によって補間されます。
注
LocationSimulatorによって発信される位置情報は補間されず、ソースに基づいて提供されます。Routeの場合、ルート ジオメトリーの座標が使用されます (互いに非常に近いもの)。GPXTrackの場合、座標は GPX データに基づいて発信されます。たとえば、2 つの座標の間に数百メートルある場合、時間設定に基づいて 2 つの座標のみが発信されます。ただし、VisualNavigatorにフィードされると、レンダリングされたマップ アニメーションはVisualNavigatorによって補間されます。
連続する Location の更新間の距離が 100 m を超える場合、VisualNavigator はアニメーションをスキップします。speedFactor が増加すると、位置情報の更新間の距離も変わります。通知の間隔がそれに応じて調整されない場合は、たとえば速度係数を 8 に変更するなら、Location の更新間の距離の一貫性を保つために、通知間隔も 125 ms (1000 ms / 8) に変更します。notificationInterval と speedFactor は反比例します。したがって、speedFactor が 3 であれば、推奨される notificationInterval は 330 ms になります。
以下のコードは enableRoutePlayback() と enableDevicePositioning() を呼び出すことで、シミュレーションされた位置情報と実際の位置情報を途切れることなく切り替える方法を示しています。
// Provides simulated location updates based on the given route.
public void enableRoutePlayback(Route route) {
herePositioningProvider.stopLocating();
herePositioningSimulator.startLocating(visualNavigator, route);
}
// Provides location updates based on the device's GPS sensor.
public void enableDevicePositioning() {
herePositioningSimulator.stopLocating();
herePositioningProvider.startLocating(visualNavigator, LocationAccuracy.NAVIGATION);
}
// Provides simulated location updates based on the given route.
private fun enableRoutePlayback(route: Route?) {
herePositioningProvider.stopLocating()
herePositioningSimulator.startLocating(visualNavigator, route!!)
}
// Provides location updates based on the device's GPS sensor.
private fun enableDevicePositioning() {
herePositioningSimulator.stopLocating()
herePositioningProvider.startLocating(visualNavigator, LocationAccuracy.NAVIGATION)
}
新しいシミュレーションを開始する前に、進行中のシミュレーションまたは実際の位置情報ソースを必ず停止する必要があります。
上のコードは、GitHubにある「Navigation」のサンプルアプリに含まれており、Java版およびKotlin版があります。
7 日前の更新










