ガイダンスを開始します
HERE SDK を使用すると、包括的なターン・バイ・ターンナビ (矢印ナビ)エクスペリエンスを構築できます。 このフィーチャーを使用すると、アプリは現在のデバイスの位置を計算されたルートと照合して確認し、ナビゲーションの指示をジャストインタイムで取得できます。
注
ナビゲーションは、publicTransit
を除くすべての利用可能なトランスポートモードでサポートされています。 公共交通機関の利用は、ナビゲーションで不確かな、予期しない結果が生じる可能性があります。
bus
ルートのナビゲーションサポートは現在制限されています : 今後リリースされる HERE SDK では、バス固有のレーンアシスタンスの改善や、バスナビゲーションのより正確なターンバイターンナビが期待されています。
トランスポートモードは、 Route
をまたいで変更される場合があります。たとえば、公園を歩いて観光地に到着した場合、車を降りる必要がある場合があります。 ルートが計算されると、トランスポート モードが Route
オブジェクトの各 Section
に添付されます。
車、トラック、タクシー、バス、スクーターのルートについては、道路とマップで車両の位置を合わせます。歩行者ルートなどの他のモードについては、舗装されていない舗装されていない舗装路やドライバーがアクセスできないその他の経路に加えて、位置を合わせることができます。 一方、高速道路などの特定の道路は歩行者用のナビゲートはできません。 自転車ルートでは、高速道路を除く利用可能なすべての経路を利用できます。
HERE SDK では、トラッキングルートがなくても トラッキングモードをサポートしています。トラッキングモードでは、現在の道路、マップマッチングした場所、および制限速度などのその他のサポート情報が提供されます。
HERE SDK に は、 視覚的なフィードバックを示すための操作矢印のための UI アセットがありません。 代わりに、ルート上で利用できるすべての情報が単純なデータ型として提供され、必要に応じて独自のアセットを選択できます。
注
ヒント : ご自身の iOS アプリケーションで使用できる再利用可能なアセットは、 HERE の MSDKUI オープンソースプロジェクトにあり ます。このプロジェクトは、 GitHub のこのリンクから利用できます。 再利用可能なアイコンの数は、 HERE の公式アイコンライブラリ に記載されています。
カスタマイズされたナビゲーションマップ ビューは、オプションでVisualNavigator
とともにレンダリングされます。 startRendering()
が呼び出されると、現在の方向を示す矢印の形式で事前設定されたインスタンス MapMarker3D
が追加され、受信位置の更新がスムーズに補間されます。 さらに、マップの向きが最適なデフォルト値に変更されます。
事前設定されたインスタンスMapMarker3D
は、独自のモデルを設定してカスタマイズすることも、無効にすることもできます。 内部的に、VisualNavigator
はLocationIndicator
インスタンスを使用するため、VisualNavigator
にLocationIndicator
カスタムを設定することもできます。 この操作が完了したら、インスタンスを手動で追加、削除、および更新する必要があります。 マップ ビューですでにLocationIndicator
インスタンスを使用している場合と同様 に、関連するマップアイテムのセクションを参照してください。
デフォルトでは、LocationIndicator
のスタイルは、VisualNavigator
に設定できるトランスポートモードによって決まります。 ルートが設定されている場合は、代わりにルートインスタンスから取得されます。 カスタムアセットを使用する場合は、クラスLocationIndicator
を介してスタイルを直接切り替える必要があります。
注
NavigationCustom Example アプリで は、ナビゲーションが停止したときにカスタムLocationIndicator
および別のタイプに切り替える方法を示します。 また、ナビゲーションパースペクティブのカスタマイズ方法も示します。
音声ガイダンスは、 任意 のプラットフォーム TTS (音声合成)ソリューションにString
として送信できる操作通知を提供します。
注
完全なオフラインサポート : オフライン マップ データがキャッシュ、インストール、またはプリロードされている場合、すべてのナビゲーションフィーチャーはインターネットに接続されていなくても動作します。 たとえば、DynamicRouteEngine
を使用して交通最適化されたルートをオンラインで検索する場合、オンライン接続が必要なフィーチャーは一部だけです。 特に記載がない限り、以下のすべてのフィーチャーはオフラインで動作します。
他のエンジンとは異なり、ガイダンスがキャッシュ、インストール、または事前にプリロードされていないリージョンに到達すると、 HERE SDK は自動的にオンラインデータのダウンロードを試みます。 その逆も同様ですが、このオフライン マップデータは、オンライン接続が利用可能であっても、デバイスで利用可能な場合に利用されます。
ターン・バイ・ターンナビ (矢印ナビ)
ターン・バイ・ターンナビ (矢印ナビ)の基本原則は、速度や方位の値などの位置情報を頻繁に受信し、道路と照合して目的のルートと比較することです。 現在地 と 次の目的地を案内する操作指示が表示されます。
ルートを出るときに、メートル単位で偏差が通知されます。 この通知は、新しいルートを計算するかどうかを決定するのに役立ちます。 最後に、位置シミュレータを使用すると、開発フェーズでルートナビゲーションをテストできます。
注 : 重要
ターン・バイ・ターンナビ (矢印ナビ)を使用するアプリケーション開発者は、想定されるすべての使用シナリオでアプリケーションを徹底的にテストして、安全で正しい動作を保証する必要があります。 アプリケーション開発者は、アプリユーザーに以下を含む ( ただし、これらに限定されない ) 義務について警告する責任があります。
- 安全でない、または違法な状況につながる可能性のある指示に従わないでください。
- すべての地域の法律に従ってください。
- 運転中に携帯電話またはそのフィーチャーの一部を使用することは禁止されている場合がありますので、ご了承ください。
- 運転中は、常にハンドルから手を離さないでください。
- 走行中は、道路の安全性を最優先にしてください。
以下のセクションのすべてのコードスニペットは 、ナビゲーションサンプルアプリの一部として GitHub でも利用できます。このアプリは、関連するコードを示し、指導中に画面をアクティブに保つなど、安定したドライビング体験とベストプラクティスを提供します。 ただし、本格的な量産対応アプリケーションのすべての側面をカバーするわけではありません。 たとえば、アプリ では、アプリ がバックグラウンドで動作している間に位置情報の更新を取得する方法は表示されません。
位置情報のバックグラウンド更新をする場合は、『位置情報の取得』ガイドの関連セクションを参照してください。 位置情報の更新を提供する限り、デバイスの画面がロックされていたり、マップ ビューが一時停止されている場合でも、すべてのナビゲーションイベントがシームレスに配信され続けます。
さらに 、 GitHub で NavigationQuickStart アプリを利用し て、数行のコードでガイダンスを開始する方法を確認することもできます。 次のセクションも参照してください。
利用開始
HERE SDK のナビゲーションフィーチャーについてより詳しく調べる前に、まず短いコードの例を参照して、音声で操作できる指示とガイダンスビューを使用してガイダンスを開始する方法を示します。
private func startGuidance(route: Route) {
do {
try visualNavigator = VisualNavigator()
} catch let engineInstantiationError {
fatalError("Failed to initialize VisualNavigator. Cause: \(engineInstantiationError)")
}
visualNavigator!.startRendering(mapView: mapView)
visualNavigator!.maneuverNotificationDelegate = self
visualNavigator!.route = route
setupLocationSource(locationDelegate: visualNavigator!, route: route)
}
func onManeuverNotification(_ text: String) {
print("ManeuverNotifications: \(text)")
}
private func setupLocationSource(locationDelegate: LocationDelegate, route: Route) {
do {
try locationSimulator = LocationSimulator(route: route,
options: LocationSimulatorOptions())
} catch let instantiationError {
fatalError("Failed to initialize LocationSimulator. Cause: \(instantiationError)")
}
locationSimulator!.delegate = locationDelegate
locationSimulator!.start()
}
このコードの抜粋では、ガイダンスビューが開始 され、提供されたroute
で定義されている宛先に到達するまで、操作手順がコンソールに出力されます ( 宣言を含むすべてのコードについては、「 NavigationQuickStart Example アプリ 」を参照してください ) 。 操作の指示はドライバーに伝えられることを意図しており、「左折して 5,000 m 先の Invalidenstra ß e に入る」などの文字列が含まれている場合があります。 操作方法の詳細な説明も利用できます。詳細については、以下のセクションを参照してください。
上記では、 HERE SDK のシミュレーションフィーチャーを使用して位置情報の更新を取得しています。 もちろん、VisualNavigator
に実際の位置情報の更新をフィードすることもできます。
ナビゲーションアプリの基本原則は次のとおりです。
Route
を作成します。 走行するルートがないと、ガイダンスを開始できません。 - インスタンス
VisualNavigator
を作成してレンダリングを開始します ( または、独自のガイダンスビューをレンダリングする場合はインスタンスNavigator
を作成します ) 。 Route
をVisualNavigator
に設定します。 - 位置情報の更新が
VisualNavigator
に送られました。 位置情報がないと、ルート沿いのルートの進行状況を検出できません。 これにより、上に示したようにシミュレートが可能です。また、実際の位置情報の更新ができます。
利用開始時は、 GitHub の NavigationQuickStart サンプルアプリ を参照して、この仕組みを確認してください。 そこでは、 HERE SDK が提供する多くのナビゲーションフィーチャーの詳細を確認できます。
注
Waypoint
を設定する場合 、ドライバーが道路のどちら側に到着するかを、sideOfStreetHint
に設定して調整できます。 ドライバーが動いている場合、ベアリング値を headingInDegrees
に設定 Waypoint
することで、初期の方向を決定できます。 これにより、次の目的地がドライバーの後ろにある場合に、不要な U ターンを避けることができます。 これは、不要な道路横断を避けるためなど、歩行者のルートを最適化するのにも役立ちます。
ナビゲーターを使用して、ガイダンスイベントを検知
前述のように、目的地へのナビゲーションを開始する前に、次の 2 つのことを行う必要があります。
- 走行する
Route
。 ナビゲーションを開始するには、Navigator
またはVisualNavigator
インスタンスにRoute
を設定する必要があります。 Navigator
または VisualNavigator
インスタンスにユーザーがいる場所を定期的に通知する場所ソース。
ルートがすでに計算されていない場合は、次のように作成します。 Route
インスタンスを取得中で あることがここに示されます。 アプリをトラッキングモードでのみ開始する場合は、この手順をスキップできます。
注
ターン・バイ・ターンナビ (矢印ナビ)中に、Navigator
またはVisualNavigator
インスタンスから現在のLocation
と同期されたすべてのManeuver
情報を取得します。 移動中は 、Route
オブジェクトから直接Manuever
データを取得しないでください。
ガイダンスを開始するには、 2 つの選択肢があります。 ヘッドレス Navigator
を使用するか、またはVisualNavigator
のサポートを受け てください。 Navigator
は VisualNavigator
のサブセットを提供するため、どちらも同じインターフェイスを提供しますが、VisualNavigator
は、個別の Location
更新間のスムーズな補間などのフィーチャーを備えた視覚的なレンダリング支援を最上位に提供します。
別の要件は、Location
インスタンスを提供することです。現在の場所で頻繁に更新を行わないとナビゲーションを実行できないためです。 このため には、 GitHub にあるプロバイダの実装を使用できます。
プラットフォームポジショニングソリューションを実装するか、 HERE SDK ポジショニングフィーチャーを使用するか または ロケーションシミュレータを設定することで、新しい場所にフィードできます。
基本的な情報フローは次のとおりです。
ロケーションプロバイダ => ロケーション => (Visual ) ナビゲータ => イベント
Location
任意のソースを「ロケーションプロバイダ」として設定できます。 onLocationUpdated()
Navigator
またはVisualNavigator
でのみ呼び出す必要 があります。
開発者は、有効な場所でVisualNavigator
にフィードする責任があります。 VisualNavigator
は、受信した各場所について、ルート沿いの進行状況を示す適切なイベント(操作、予想されるルートからの逸脱など)を使用して応答します。 結果のイベントは、提供された位置信号の精度と周波数に依存します。
まず、参照実装の新しいインスタンスを作成して場所を取得します。
herePositioningProvider = HEREPositioningProvider()
次に、新しい VisualNavigator
インスタンスを作成し HEREPositioningProvider
、上記のからへのデリゲートとして設定します。 この VisualNavigator
クラスは、場所を受け取る onLocationUpdated(location:)
メソッドを定義する LocationDelegate
プロトコルに準拠しています。
do {
try visualNavigator = VisualNavigator()
} catch let engineInstantiationError {
fatalError("Failed to initialize VisualNavigator. Cause: \(engineInstantiationError)")
}
herePositioningProvider.startLocating(locationDelegate: visualNavigator,
accuracy: .navigation)
さらに、トラッキングするルートを設定してください ( トラッキングモードにする予定がある場合のみ ) 。
visualNavigator.route = route
注
VisualNavigator
のレンダリング機能を使用しない場合は 、代わりにクラスNavigator
を使用することもできます。 このクラスは、フードの下の同じコードを使用 し、VisualNavigator
とまったく同じように動作しますが、特殊なナビゲーションビューのレンダリングはサポートしていません。
次のステップでは、ルートの進行状況、現在の場所、次のルート変更の進行状況について通知を受け取るように、いくつかの代理人を設定できます。
visualNavigator.navigableLocationDelegate = self
visualNavigator.routeDeviationDelegate = self
visualNavigator.routeProgressDelegate = self
HERE では、 RouteProgressDelegate
、 NavigableLocationDelegate
、および RouteDeviationDelegate
の各プロトコルを満たすための準拠メソッドを設定しています。
func onRouteProgressUpdated(_ routeProgress: RouteProgress) {
let distanceToDestination = routeProgress.sectionProgress.last!.remainingDistanceInMeters
print("Distance to destination in meters: \(distanceToDestination)")
let trafficDelayAhead = routeProgress.sectionProgress.last!.trafficDelay
print("Traffic delay ahead in seconds: \(trafficDelayAhead)")
let nextManeuverList = routeProgress.maneuverProgress
guard let nextManeuverProgress = nextManeuverList.first else {
print("No next maneuver available.")
return
}
let nextManeuverIndex = nextManeuverProgress.maneuverIndex
guard let nextManeuver = visualNavigator.getManeuver(index: nextManeuverIndex) else {
return
}
let action = nextManeuver.action
let roadName = getRoadName(maneuver: nextManeuver)
let logMessage = "'\(String(describing: action))' on \(roadName) in \(nextManeuverProgress.remainingDistanceInMeters) meters."
if previousManeuverIndex != nextManeuverIndex {
showMessage("New maneuver: " + logMessage)
} else {
showMessage("Maneuver update: " + logMessage)
}
previousManeuverIndex = nextManeuverIndex
}
func onNavigableLocationUpdated(_ navigableLocation: NavigableLocation) {
guard navigableLocation.mapMatchedLocation != nil else {
print("The currentNavigableLocation could not be map-matched. Are you off-road?")
return
}
let speed = navigableLocation.originalLocation.speedInMetersPerSecond
let accuracy = navigableLocation.originalLocation.speedAccuracyInMetersPerSecond
print("Driving speed: \(String(describing: speed)) plus/minus accuracy of \(String(describing: accuracy)).")
}
func onRouteDeviation(_ routeDeviation: RouteDeviation) {
guard let route = visualNavigator.route else {
return
}
var currentGeoCoordinates = routeDeviation.currentLocation.originalLocation.coordinates
if let currentMapMatchedLocation = routeDeviation.currentLocation.mapMatchedLocation {
currentGeoCoordinates = currentMapMatchedLocation.coordinates
}
var lastGeoCoordinates: GeoCoordinates?
if let lastLocationOnRoute = routeDeviation.lastLocationOnRoute {
lastGeoCoordinates = lastLocationOnRoute.originalLocation.coordinates
if let lastMapMatchedLocationOnRoute = lastLocationOnRoute.mapMatchedLocation {
lastGeoCoordinates = lastMapMatchedLocationOnRoute.coordinates
}
} else {
print("User was never following the route. So, we take the start of the route instead.")
lastGeoCoordinates = route.sections.first?.departurePlace.originalCoordinates
}
guard let lastGeoCoordinatesOnRoute = lastGeoCoordinates else {
print("No lastGeoCoordinatesOnRoute found. Should never happen.")
return
}
let distanceInMeters = currentGeoCoordinates.distance(to: lastGeoCoordinatesOnRoute)
print("RouteDeviation in meters is \(distanceInMeters)")
}
RouteProgressDelegate
の内部では、渡されたRoute
インスタンスのSection
ごとの進行状況に関する詳細情報にアクセスできます。 ルートは、ウェイポイントおよびトランスポートモードの数に基づいて複数のセクションに分割できます。 remainingDistanceInMeters
および trafficDelay
はすでにセクションごとに累積されています。 SectionProgress
一覧表の最後の項目を確認して、目的地までの全体的な残り距離と全体的な推定交通遅延を取得します。
trafficDelay
は Route
データが計算された時刻に基づいているため 、ガイダンス中の交通障害による遅れは更新されません。 値は、初期データに基づいて進行中のセクションに沿ってのみ更新されます。 現在 のトラフィック状況に基づいて、最適化されたルートを定期的に要求するには、DynamicRoutingEngine
を使用します。
内部 RouteProgressDelegate
では、前方にある次の操作にアクセスすることもできます。 このために、次のものを使用します maneuverIndex
。
let nextManeuverList = routeProgress.maneuverProgress
guard let nextManeuverProgress = nextManeuverList.first else {
print("No next maneuver available.")
return
}
let nextManeuverIndex = nextManeuverProgress.maneuverIndex
guard let nextManeuver = visualNavigator.getManeuver(index: nextManeuverIndex) else {
return
}
maneuver
取得した情報 visualNavigator
を使用して、ドライバーが次のアクションや、このアクションが実行されるまでの距離などのその他の役立つ情報を表示するためのディスプレイを作成できます。 上記の例のようなデバッグ目的で使用されている場合を除き、テキスト表現には使用しないことをお勧めします。 代わりに音声ガイダンスを使用してください ( 以下を参照 ) 。
ただし、ローカライズされた道路名または番地 ( 高速道路番号など ) を表示すると便利です。これらの住所は、次のように取得できます。
func getRoadName(maneuver: Maneuver) -> String {
let currentRoadTexts = maneuver.roadTexts
let nextRoadTexts = maneuver.nextRoadTexts
let currentRoadName = currentRoadTexts.names.defaultValue()
let currentRoadNumber = currentRoadTexts.numbersWithDirection.defaultValue()
let nextRoadName = nextRoadTexts.names.defaultValue()
let nextRoadNumber = nextRoadTexts.numbersWithDirection.defaultValue()
var roadName = nextRoadName == nil ? nextRoadNumber : nextRoadName
if maneuver.nextRoadType == RoadType.highway {
roadName = nextRoadNumber == nil ? nextRoadName : nextRoadNumber
}
if maneuver.action == ManeuverAction.arrive {
roadName = currentRoadName == nil ? currentRoadNumber : currentRoadName
}
return roadName ?? "unnamed road"
}
上に示すように、currentRoadTexts.names.defaultValue
経由でデフォルトの道路テキストを直接取得できます。 ほとんどの場合、この道路名はローカルの標識に示されている通りになります。
または、currentRoadTexts.names.preferredValue(for: [locale])
経由で、優先言語のリストに基づいて道路名のローカライズされたテキストを取得 できます。 使用できる言語がない場合は、既定の言語が返されます。
注
RoadTextsDelegate
を使用 して、現在運転中の状況RoadTexts
(トラッキングモード中など)について通知を受け取ることができます。
デバイスの GPS センサーによって提供された位置が正確でない可能性があるため、 VisualNavigator
は内部的に、 NavigableLocation
物体の一部として当社に提供されたマップマッチした場所を計算します。 この場所は、通りなどのナビゲーション可能な経路にあることが想定されています。 ただし、ユーザーが車を降りた場合や、 GPS 信号が弱すぎてマップマッチした場所を見つけることができない場合にも、軌道から外れてしまうことがあります。
マップマッチした場所を使用して、ユーザーに視覚的なフィードバックを提供することをお勧めします。 ユーザーがオフロードにいる場合など、位置情報を地図で照合できなかった場合にのみ、不一致にフォールバックすると便利 originalLocation
です。 以下 VisualNavigator
では、のレンダリング機能を使用して、マップ ビューを自動的に更新することを選択します。
注
ナビゲーション中は、 ManeuverAction
列挙型 (enum) によって示されている操作アイコンを視覚的インジケータとして表示することをお勧め します。また、走行を開始する前に、操作をプレビューするために、Maneuver
指示テキスト (nextManeuver.text
) がより多くのリストに収まるようにします。 これらのローカライズされた指示は記述的であり、進行中のガイダンスのコンテキスト外で理解できます。 ただし、一般 的には、オープンソースの HERE Icon ライブラリ にある対応するManeuverAction
アイコンと一緒に表示できます。 詳細については 、「ルーティング 」セクションを参照してください。
反対に nextManeuver.roadTexts
、nextManeuver.nextRoadTexts
およびnextManeuver.exitSignTexts
は 、ナビゲーション中のターンバイターン操作の一部として表示されます。 これらはManeuver
、Navigator
または VisualNavigator
から取得された場合にのみ空では ありません。 Route
インスタンスから取得した場合、これらの属性は常に空になります。
高速道路などの一部の道路には名前がありません。 そのような場合は、道路番号の取得を試みることができます。 また、世界のどこかに名前のない道路がある可能性もあることにも注意してください。
次の表に、操作手順のプロパティの使用方法を示します。
操作手順のプロパティ |
RoutingEngine | Navigator / VisualNavigator | 例 |
maneuver.text | 空でない文字列を提供します。 | 空でない文字列を提供します。 | 出力例 text : "Detmolder Stra ß e を A100 方面に右折します。 " |
maneuver.roadTexts | 空の文字列を提供します。 | 空でない文字列を提供します。 | 出力例 roadTexts.names.defaultValue() : "Stadtring" 。 |
maneuver.nextRoadTexts | 空の文字列を提供します。 | 空でない文字列を提供します。 | 出力例 nextRoadTexts.names.defaultValue() : "Halenseestra ß e" |
Operation.exitSignTexts | 空の文字列を提供します。 | 空でない文字列を提供します。 | 出力例 exitSignTexts.defaultValue() : " ハンブルク " 。 |
注
上記のイベントを自分でトリガーする必要はありません。 代わりに、 VisualNavigator
は、ロケーションプロバイダの実装から取得されたものとして、提供された場所で反応します。
ルートの逸脱が検出された場合は、ユーザーを目的地にリルーティングするかどうかを distanceInMeters
に基づいて決定できます。 フルルートの再計算では、同じルートパラメータを使用することがあります。 ルートに戻る方法の詳細については、次のセクションを参照してください。
上の例では、に含まれている座標に基づいて距離を計算します RouteDeviation
。distanceInMeters
。 この距離は、ルート上の予想される場所と実際の場所の間の直線距離です。 その距離が遠すぎると判断 visualNavigator
された場合は、インスタンスへの新たに計算されたルートを設定できます。それ以降のすべてのイベントは、新しいルートに基づいて作成されます。
ドライブガイダンスのシナリオでは、 lastLocationOnRoute
とmapMatchedLocation
が null
の場合があることに注意してください。 routeDeviation.lastLocationOnRoute
がnull
の場合 、ユーザーはルートを走行していませんでした。これは、開始位置が道路ネットワーク から離れている場合に発生することがあります。 通常、 Navigator
/VisualNavigator
はLocation
の更新内容を道路と一致させようとします。 ドライバーが遠すぎると、その場所を見つけることができません。
注
イベントが非同期で配信されるため、古いルートについてはキュー内の以前のイベントが 1 回だけ配信されることがあります。 必要に応じて、新しいルートを設定した後で新しい代理を追加して、この問題を回避できます。
ナビゲーションサンプルアプリ に、偏差を検出する方法が示されています。
道路標識のイベントを聞きます
道に沿って多くの標識を見つけることができます。 運転中に、RoadSignWarningDelegate
を設定することで、これらの標識に関する詳細な通知を受信できます。
結果の RoadSignWarning
イベントには、RoadSignType
や RoadSignCategory
などの情報を含むシールドに関する情報が含まれます。
デフォルトでは、イベントは他の警告と同じ距離のしきい値で開始されます。
- 高速道路を利用する場合、約 2000 メートル先にイベントが発生します。
- 田舎道では、約 1500 メートル先にイベントが発生します。
- 都市部では、約 1000 メートル先にイベントが発生します。
RoadSignWarningOptions
では、通知を受け取る標識のフィルタを設定できます。
優先道路標識の例をいくつか示します。 すべての道路標識が含まれているわけではありません。 RoadSignType
はサポートされているすべてのタイプを一覧表示 たとえば 、制限速度 を示す道路標識は、専用のSpeedLimitDelegate
で検知できるため、除外されます。
次のコード スニペット は、使用例を示しています。
private func setupRoadSignWarnings() {
var roadSignWarningOptions = RoadSignWarningOptions()
roadSignWarningOptions.vehicleTypesFilter = [RoadSignVehicleType.trucks, RoadSignVehicleType.heavyTrucks]
visualNavigator.roadSignWarningOptions = roadSignWarningOptions
}
...
func onRoadSignWarningUpdated(_ roadSignWarning: RoadSignWarning) {
print("Road sign distance (m): \(roadSignWarning.distanceToRoadSignInMeters)")
print("Road sign type: \(roadSignWarning.type.rawValue)")
if let signValue = roadSignWarning.signValue {
print("Road sign text: " + signValue.text)
}
}
RoadSignWarning
イベントは次の 2 回正確に発行されます。
DistanceType
が AHEAD
で、distanceToRoadSignInMeters
が 0 より大きい場合。 DistanceType
が PASSED
0 の場合 distanceToRoadSignInMeters
。
注
スピードカメラ、道路標識、現実的なビューなど、道路沿いの単一のオブジェクトについて通知する位置警告の場合、一度に発生するアクティブな警告は常に1つだけです。 これは、各 ahead
イベントの後に常に passed
イベントが続くことを意味し、1つのオブジェクトに対する2つの先行警告が同時にアクティブになることを回避します。
トールの停止音を聞きます
もう 1 つの警告のタイプは次の料金所でのでき事を確認するTollStopWarningDelegate
である。
このイベントは、他の警告と同じ距離のしきい値で開始されます。
- 高速道路を利用する場合、約 2000 メートル先にイベントが発生します。
- 田舎道では、約 1500 メートル先にイベントが発生します。
- 都市部では、約 1000 メートル先にイベントが発生します。
すべての Warners と同様に、イベントはトラッキングモードおよびターン・バイ・ターンナビ (矢印ナビ)中に発行されます。
TollBoothLane
のクラス内では、料金所のどの車線が車両タイプに適しているか、および受け入れられている支払い方法などの他の情報を見つけることができます。
func onTollStopWarning(_ tollStop: TollStop) {
let lanes = tollStop.lanes
let laneNumber = 0
for tollBoothLane in lanes {
logLaneAccess(laneNumber, tollBoothLane.access)
let tollBooth = tollBoothLane.booth
let tollCollectionMethods = tollBooth.tollCollectionMethods
let paymentMethods = tollBooth.paymentMethods
for collectionMethod in tollCollectionMethods {
print("This toll stop supports collection via: \(collectionMethod).")
}
for paymentMethod in paymentMethods {
print("This toll stop supports payment via: \(paymentMethod).")
}
}
}
func logLaneAccess(_ laneNumber: Int, _ laneAccess: LaneAccess) {
print("Lane access for lane \(laneNumber).")
print("Automobiles are allowed on this lane: \(laneAccess.automobiles).")
print("Buses are allowed on this lane: \(laneAccess.buses).")
print("Taxis are allowed on this lane: \(laneAccess.taxis).")
print("Carpools are allowed on this lane: \(laneAccess.carpools).")
print("Pedestrians are allowed on this lane: \(laneAccess.pedestrians).")
print("Trucks are allowed on this lane: \(laneAccess.trucks).")
print("ThroughTraffic is allowed on this lane: \(laneAccess.throughTraffic).")
print("DeliveryVehicles are allowed on this lane: \(laneAccess.deliveryVehicles).")
print("EmergencyVehicles are allowed on this lane: \(laneAccess.emergencyVehicles).")
print("Motorcycles are allowed on this lane: \(laneAccess.motorcycles).")
}
支払いの正確な価格や料金所の場所など、詳細な情報を Route
オブジェクトの一部として利用できます。 このような情報は、旅程を開始する前にルートから抽出する場合に役立ちます。 たとえば、タップ可能なアイテム MapMarker
を使用して、ルートに沿って料金所を示すことができます。 ガイダンス中に、このような詳細情報が原因でドライバーの注意が散漫になる可能性があります。 そのため、事前に情報を提供することをお勧めします。
スクールゾーンの警告イベントの処理
他の警告と同様に、専用の SchoolZoneWarningDelegate
を設定することもできます。
func onSchoolZoneWarningUpdated(_ schoolZoneWarnings: [heresdk.SchoolZoneWarning]) {
for schoolZoneWarning in schoolZoneWarnings {
if schoolZoneWarning.distanceType == DistanceType.ahead {
print("A school zone ahead in: \(schoolZoneWarning.distanceToSchoolZoneInMeters) meters.")
print("Speed limit restriction for this school zone: \(schoolZoneWarning.speedLimitInMetersPerSecond) m/s.")
if let timeRule = schoolZoneWarning.timeRule {
if timeRule.appliesTo(dateTime: Date()) {
print("Note that this school zone warning currently does not apply.")
}
}
} else if schoolZoneWarning.distanceType == DistanceType.reached {
print("A school zone has been reached.")
} else if schoolZoneWarning.distanceType == DistanceType.passed {
print("A school zone has been passed.")
}
}
}
通知のスレッシュホールドはすべてのリージョンに適用され、次の方法 SchoolZoneWarningOptions
で設定できます。
private func setupSchoolZoneWarnings() {
var schoolZoneWarningOptions = SchoolZoneWarningOptions()
schoolZoneWarningOptions.filterOutInactiveTimeDependentWarnings = true
schoolZoneWarningOptions.warningDistanceInMeters = 150
visualNavigator.schoolZoneWarningOptions = schoolZoneWarningOptions
}
デフォルトの距離しきい値は、 API リファレンス にあります。
ルート偏差を処理します
上記のセクションで見たように、このイベント RouteDeviation
を使用して、ドライバーが元ルートを離れたときに検出できます。 これは、たとえばドライバーが運転中に代替ルートやルート オプションについて以前に選択した内容を無視して、目的地まで別のルートを選択した場合など、偶然または意図的に発生する可能性があることに注意してください。
上記のように 、ドライバーの現在の位置からルート上の最後の既知の位置までの距離を検出できます。 その距離に基づいて、アプリケーションは、新しいルート全体を計算する時か、ルート代替およびルートオプションの選択を維持するためにユーザーを元のルートに誘導する時かを決定できます。
HERE SDKは ルートを自動的に再計算することはなく、偏差距離のみを記録するため、ルートに戻る方法に関するロジックはアプリ側で実装する必要があります。
注
ヒント: このイベントRouteDeviation
は、新しいロケーションが更新されるたびに起動されます。 イベントの不必要な処理を避けるために、ドライバーがまだ逸脱しているかどうかを確認するために数秒待つことをお勧めします。 イベントが発生しなくなった場合は、ドライバーがルートに戻っていることを意味します。 ルート計算は非同期的に行われ、新しいルート計算を開始するタイミングと方法がアプリケーションによって決定されることに注意してください。 ただし、 Navigator
または VisualNavigator
インスタンスへのナビゲーション中にいつでも新しいルートを設定でき、今後のイベントは新しく設定された Route
インスタンスに基づいて更新されます。
ユーザーがオフロードである場合もあることを言及する必要があります。 新しいルートを設定した後も、ユーザはまだオフロードにいる可能性があります。そのため、ユーザはまだルートをたどることができません。 このような場合でも、新しく設定されたルートの偏差イベントを受信し、 routeDeviation.lastLocationOnRoute
は、nullになります。 ユーザーの現在の位置が変更されていない場合は、新しいルート計算を再開しないことをお勧めします。
HERE SDK には、ルートの逸脱を処理するための複数の API があります。
- 新しい、または更新した
RouteOptions
を使用して新しい代替ルートを提供するために、RoutingEngine
を使用してルート全体を再計算します。 ユーザーの現在の位置を新しい開始点として使用する場合は、最初のWaypoint
の進行方向も指定してください 。 - このメソッド
returnToRoute()
を使用して、最初に選択した代替ルートに到達するための新しいルートを計算します。 オンライン RoutingEngine
およびOfflineRouteEngine
で利用できます。 OfflineRouteEngine
を使用して計算されたルート には、交通情報が含まれなくなっていることに注意してください。 - 元のルート上にある新しい出発地を使用して
routingEngine.refreshRoute()
で古いルートを更新し、必要に応じてルート オプションを更新します。RouteHandle
は元のルートを識別する必要があります。 このオプションでは、逸脱した場所からルートに戻るパスは提供されないため、それ自体では、逸脱のユースケースには適していません。 - さらに、HERE SDKは、現在のトラフィック状況に基づいて最適化されたルートを定期的に要求できる
DynamicRoutingEngine
を提供します。 RouteHandle
を必要とするため、オンラインで計算されたルートが必要です。 これは、ユーザーがまだルートをたどっている間に、より良いルートを見つけることを目的としています。 したがって、入力として現在の位置を必要としますが、偏差のユースケースには最適な選択ではない場合があります。
1 番めと 3 番めのオプションについては 、「ルーティング 」セクションで説明します。 元のルートを更新する 3 番目のオプションでは、逸脱した場所からルートに戻るパスは提供されません。 このため、以下では説明しません。 ただし、アプリケーションは、ルートから移動された部分を削除して、ユーザーが自分で新しい出発地点に到達できるようにするために使用できます。
逸脱した場所の距離や位置などのパラメータに基づいて、アプリケーションはドライバーに提供するオプションを決定する必要があります。
ただし、一般的な推奨事項は 、逸脱が検出された 場合にreturnToRoute()
を使用することです。これは、アプリがユーザーが選択する複数の代替ルートを提供している場合に、ユーザーを元の選択した代替ルートに戻す最適なオプションであるためです。
注
GPS ソースから提供された場所がルートに十分近くなると、リソースを節約するためのマップマッチングが行われません。 その場所がルートから離れている場合にのみ、 HERE SDK はその場所を道路にマップしようとします。
逸脱後のルートに戻る
RoutingEngine
またはOfflineRoutingEngine
を使用して、元のルートに戻るルートをオンラインまたはオフラインで計算 します。 この方法returnToRoute()
は、最初に選択したルートを維持しながら、ドライバーができるだけ早くルートに戻るのを支援する場合に使用します。
注
returnToRoute()
は、ルート逸脱を処理するための選択肢の1つにすぎません。 代替オプションについては、上記を参照してください。 たとえば、場合によっては、ユーザーの目的地までの新しいルート全体を計算することをお勧めします。
現在 、このフィーチャーreturnToRoute()
はエンジンと同じトランスポートモードをサポート しています。、OfflineRoutingEngine
およびRoutingEngine
の両方を使用できます。 RoutingEngine
でメソッドを実行する場合 、パブリックトランジットルートのみがサポートされません。RoutingEngine
の他のすべての利用可能なトランスポートモードがサポートされます。
注
このOfflineRoutingEngine
メソッドのreturnToRoute()
には、キャッシュ、またはすでにダウンロードされたマップ データが必要です。 ほとんどの場合、ドライバーがルートから逸脱している間に、元のルートに戻るパスがすでにキャッシュされている可能性があります。 ただし、逸脱が大きすぎる場合は、代わりに新しいルートを計算することを検討してください。
ルートの計算には、次のパラメータが必要です。
- オリジナルの
Route
。 Navigator
/ VisualNavigator
から入手できます。 - また、すでに走行したルートの一部を設定する必要があります。 この情報は
RouteDeviation
イベントによって提供されます。 - 新しい開始地点の
Waypoint
。ドライバーの現在のマップと一致する場所である可能性があります。
オンラインRoutingEngine
を使用する場合、下の Route
に RouteHandle
が含まれている必要があります。またはートの計算結果が NO_ROUTE_HANDLE
エラーとなります。 OfflineRoutingEngine
の場合、この操作は不要です。
新しい出発地点は 、次のイベントRouteDeviation
から取得できます。
var currentGeoCoordinates = routeDeviation.currentLocation.originalLocation.coordinates
if let currentMapMatchedLocation = routeDeviation.currentLocation.mapMatchedLocation {
currentGeoCoordinates = currentMapMatchedLocation.coordinates
}
Waypoint newStartingPoint = Waypoint(currentGeoCoordinates)
オンラインRoutingEngine
では 、完全に新しいルートが計算されることがあります。たとえば、ユーザーが以前に選択したルートの代替ルートよりも早く目的地に到達できる場合です。 OfflineRoutingEngine
は 、ルートの非移動部分を誤って再利用します。
一般に、アルゴリズムは元のルートに戻る最速の方法を探しますが、宛先までの距離も考慮します。 新しいルートは、可能であれば元のルートの形状を保持しようとします。
まだ走行していないストップオーバー はスキップされません。 パススルーウェイポイントの場合、新しいルートでそれらのルートがまったく考慮される保証はありません。
任意で、ドライバーの見出し方向を設定することで、ルート計算を改善できます。
if currentMapMatchedLocation.bearingInDegrees != nil {
newStartingPoint.headingInDegrees = currentMapMatchedLocation.bearingInDegrees
}
最後に、新しいルートを計算します。
routingEngine.returnToRoute(originalRoute,
startingPoint: newStartingPoint,
lastTraveledSectionIndex: routeDeviation.lastTraveledSectionIndex,
traveledDistanceOnLastSectionInMeters: routeDeviation.traveledDistanceOnLastSectionInMeters) { (routingError, routes) in
if (routingError == nil) {
let newRoute = routes?.first
} else {
}
}
注
CalculateRouteCompletionHandler
が再利用されるため、ルートのリストが提供されます。 ただし、リストに含まれるルートは 1 つだけです。 エラー処理は、 RoutingEngine
と同じロジックに従います。
オンラインおよびオフラインでの使用に関する一般的なガイドラインとして 、このフィーチャーreturnToRoute()
は、その先にある originalRoute
のすでに計算された部分を再利用しようとします。 トラフィックデータは、RoutingEngine
が、オンラインで使用された場合にのみ更新され、反映されます。
作成された新しいルートも 、originalRoute
で検出されたものと同じものOptimizationMode
を使用します。
ただし、最良の結果を得る RoutingEngine
には、オンラインを使用してトラフィックを最適化したルートを取得することをお勧めします。
より適切なルートを動的に検索
現在のトラフィック状況に基づいて、最適化されたルートを定期的に要求するには、DynamicRoutingEngine
を使用します。 このエンジンは、走行中の現在のルートよりも速い( ETA に基づいて)新しいルートを検索します。
DynamicRoutingEngine
には、オンライン接続と RouteHandle
が必要です。 オフラインでより適切なルートを検索しようとした場合、または RouteHandle
が有効になっていない 場合、ルーティングエラーが伝播されます。
var carOptions = CarOptions()
carOptions.routeOptions.enableRouteHandle = true
DynamicRoutingEngineOptions
を設定すると 、より適切なルートで通知を受け取る前にminTimeDifference
を定義できます。 は minTimeDifference
、現在設定されているルートの残りの ETA と比較されます。 で DynamicRoutingEngineOptions
は、 pollInterval
エンジンがより適切なルートを検索する頻度を決定するようにを設定することもできます。
private class func createDynamicRoutingEngine() -> DynamicRoutingEngine {
let minTimeDifferencePercentage = 0.1
let minTimeDifferenceInSeconds: TimeInterval = 1
let pollIntervalInSeconds: TimeInterval = 5 * 60
let dynamicRoutingOptions =
DynamicRoutingEngineOptions(minTimeDifferencePercentage: minTimeDifferencePercentage,
minTimeDifference: minTimeDifferenceInSeconds,
pollInterval: pollIntervalInSeconds)
do {
return try DynamicRoutingEngine(options: dynamicRoutingOptions)
} catch let engineInstantiationError {
fatalError("Failed to initialize DynamicRoutingEngine. Cause: \(engineInstantiationError)")
}
}
minTimeDifference
を0 に設定すると、イベントは発生しません。 同じことがminTimeDifferencePercentage
にも当てはまり ます。 イベントを取得するには、値 >=0 を設定してください。
より適切なルートを受信すると、元のルートとの差 route
がメートルと秒で表示されます。
private func startDynamicSearchForBetterRoutes(_ route: Route) {
do {
try dynamicRoutingEngine.start(route: route, delegate: self)
} catch let instantiationError {
fatalError("Start of DynamicRoutingEngine failed: \(instantiationError). Is the RouteHandle missing?")
}
}
func onBetterRouteFound(newRoute: Route,
etaDifferenceInSeconds: Int32,
distanceDifferenceInMeters: Int32) {
print("DynamicRoutingEngine: Calculated a new route.")
print("DynamicRoutingEngine: etaDifferenceInSeconds: \(etaDifferenceInSeconds).")
print("DynamicRoutingEngine: distanceDifferenceInMeters: \(distanceDifferenceInMeters).")
}
func onRoutingError(routingError: RoutingError) {
print("Error while dynamically searching for a better route: \(routingError).")
}
提供され たetaDifferenceInSeconds
distanceDifferenceInMeters
に基づい て、現在のルートと比較して、newRoute
を使用するかどうかをアプリケーションが決定できます。 その場合は、いつでもVisualNavigator
またはNavigator
に設定できます。
注
DynamicRoutingEngine
は 、新たに設定されたルートを認識しません。 つまり、ルートの逸脱を検出し、たとえばroutingEngine.returnToRoute(...)
を呼び出して新しいルートを並行して計算しようとする場合 、navigator
インスタンスに新しいルートが設定された後でDynamicRoutingEngine
に通知する必要があります。 そのため には、stop()
を呼び出してからstart(...)
dynamicRoutingEngine
インスタンスを呼び出し、新しいルートで再度開始します。 ルートがonBetterRouteFound()
コールバックの外側に設定された navigator
直後に行うことができます。 このRouteDeviation
イベントを使用 すると、ユーザーがルートから逸脱した距離を計算できます ( 逸脱後のルートに戻るを参照 ) 。
簡単にするために、新しいルートを設定するための推奨フローは次のようになります。
- 新しいルートを設定するかどうかを決定します。
- 「はい」の場合は、
DynamicRoutingEngine
を停止します。 - 新しいルートを設定します:
navigator.route = newRoute
。 - 新しい ルートで
DynamicRoutingEngine
を開始します。
イベントonBetterRouteFound()
の外部で、次の手順を呼び出してください。 新しい位置情報の更新を受信する場合は、ローカルフラグを使用して上記の手順に従います。たとえば、 dynamicRoutingEngine.updateCurrentLocation(..)
をコールする前に、以下を参照してください。
ガイダンス中に新しいルートを渡すと、ユーザーエクスペリエンスに影響が出る可能性があります。変更についてユーザーに通知することをお勧めします。 また、ユーザーが条件を事前に定義できるようにすることもお勧めします。 たとえば、 etaDifferenceInSeconds
において新しいルートを走行する正当性はありません。
注
DynamicRoutingEngine
は 交通情報および ETA を定期的に更新するために使用できますが 、新しいルートが異なるとは限りません。 さらに、 DynamicRoutingEngine
はインフォームをオン distanceDifferenceInMeters
にしますが、ルートの長さが変更されていない場合、ルートのシェイプが同じであるとは限りません。 ただし、 ETA のみが変更され、長さが同じ場合、交通状況の更新により ETA のみが更新された可能性があります。 元のルートにとどまることが重要な場合 routingEngine.refreshRoute()
は、ルートシェイプの座標を比較するか、または独自のルートを計算することを検討する必要があります。 呼び出し refreshRoute()
ても ルートの形状は変更されません。 詳細については、「ルーティング」セクションを参照してください。 反対 DynamicRoutingEngine
に、の用途はより適切なルートを見つけることであり、そのためには新しいルート形状をたどり、交通の障害物を回避することが最も望ましいことに注意してください。 また、より適切なルートは、前方のルートに交通障害物が存在する(または存在しなくなった)場合にのみ発見できます。
ドライバーの最後のマップマッチングした場所 を更新し、 取得後すぐにDynamicRoutingEngine
( RouteProgress
またはNavigableLocation
更新の一部として ) に設定してください。 これは、より適切なルートが常にドライバーの現在の位置に近い位置から開始されるようにするために重要です。
dynamicRoutingEngine.updateCurrentLocation(mapMatchedLocation: lastMapMatchedLocation,
sectionIndex: routeProgress.sectionIndex)
DynamicRoutingEngine
は、ルート上にあるマップと一致する位置が必要です。 ユーザーがルートから逸脱している場合、RoutingError.couldNotMatchOrigin
が届きます。
lastMapMatchedLocation
NavigableLocationListener
および sectionIndex
RouteProgressListener
から取得できます 。 updateCurrentLocation()
からイベントを受信する場合は、RouteProgressListener
を呼び出すことをお勧めします。
目的地に到着すると、エンジンは自動的に停止しません。 そのため 、エンジンが不要になったときにstop()
をコールすることをお勧めします。
これの実装例について は、対応するナビゲーションの例アプリを参照してください。
ルートの交通情報を更新
交通遅延時間を含む最新の到着時間( ETA )を提供し、現在のルートを超える交通の障害物について通知することが重要です。 旅程の交通情報を更新する方法を教えてください。
次の 2 つのシナリオがあります。
- 既存のルートにとどまる : この場合、
RoutingEngine
を使用して、 refreshRoute()
を定期的に呼び出します。 - 交通の障害物を迂回するための適切な代替ルートを探します。
DynamicRouteEngine
を使用します。 ユーザーが新しいRoute
を走行する必要がある場合は、Navigator
またはVisualNavigator
のインスタンスに設定をする必要があります。
更新された ETA 、交通遅延、交通渋滞情報を Route
オブジェクトから直接取得できます。
これらのオプションの詳細については、上記 のセクションを参照してください。
ルートポリラインを独自にレンダリングする場合、ルート自体でのトラフィックの表示がサポートされます。 この例については 、「ルーティング」セクションを参照してください。 このセクションでは Route
、オブジェクトからトラフィック情報を抽出する方法についても説明します。
注
または 、マップでトラフィックフローレイヤをイネーブルにすることもできます。 のデフォルト設定で VisualNavigator
は、任意のズーム レベルのルートポリラインのほかに、トラフィックフロー回線が引き続き表示されます。 たとえば 、 HERE Wego アプリケーションはこのアプローチを使用して、現在の交通状況を視覚化します。
ビジュアルナビゲータを使用してマップ ビューを更新
位置の更新に自分で対応するか、またはこの目的で VisualNavigator
を使用できます。
通常、ナビゲーション中に次の操作を行います。
- マップ上の現在の位置をトラッキングします。
- 現在の方向を示す位置矢印を表示します。
- マップを現在の方向に回転させます。
- 操作矢印など、他の視覚的なアセットを追加します。
新しい位置情報イベントが発生するたびに、 VisualNavigator
に送られた元の GPS 信号から計算されたマップマッチした場所を保持する新しい NavigableLocation
が発生します。 このマップマッチした場所を使用してマップ ビューを更新できます。
ほとんどの場合、位置情報の更新は頻繁に行われますが、個別の手順で行われることに注意してください。つまり、各場所の間に数百メートルの距離がある可能性があります。 カメラを新しい場所に更新すると、少しジャンプすることがあります。
一方、VisualNavigator
のレンダリングフィーチャーを使用すると 、スムーズに補間された移動を利用できます。 ドライバーの速度に応じて、 2 つの位置更新の間の不足している座標が補間され、ターゲットマップの位置が自動的に更新されます。
さらに、は VisualNavigator
マップを傾斜させ、マップを見出し方向に回転させて、 3D 位置の矢印とを表示 LocationIndicator
します。 これらはすべて、次の 1 行のコードでアクティブ化できます。
visualNavigator.startRendering(mapView: mapView)
スクリーンショット: デバイスで実行されているターン・バイ・ターンナビ (矢印ナビ)の例。 さらに、次のものを使用して、現在の場所のトラッキングを停止できます。
visualNavigator.cameraBehavior = nil
次のコマンドを使用して再度有効にします。
visualNavigator.cameraBehavior = FixedCameraBehavior()
デフォルトでは、カメラトラッキングが有効になっています。 したがって、マップは常に現在の位置を中心に配置されます。 これを一時的に無効にすると、ユーザーが手動でパニングしたり、ナビゲーションまたは追従中にマップを操作したりできます。 3D の位置を示す矢印が移動し続けますが、マップは移動しません。 カメラトラッキングモードが再び有効になると、マップが現在の位置にジャンプし、位置情報の更新内容をスムーズにトラッキングできます。
進行中のナビゲーションを停止するには、 visualNavigator.route = nil
電話をかけ、上記の代理人を nil にリセットするか、または単に位置情報プロバイダ stop()
を呼び出します。 詳細については 、以下のストップナビゲーションセクションを参照してください。
ソースコードの全文について は、対応するナビゲーションのサンプルアプリを確認してください。
ナビゲーションエクスペリエンスをカスタマイズします
NavigationCustom Example アプリで は、ナビゲーションが停止したときにカスタムLocationIndicator
および別のタイプに切り替える方法を示します。 また、ナビゲーションパースペクティブのカスタマイズ方法も示します。 GitHubでサンプルアプリを探します。
CameraBehavior
では、ガイダンス中のマップ ビューの外観をカスタマイズできます。 DynamicCameraBehavior
を使用して自動ズームの動作を設定 できます。または、FixedCameraBehavior
を使用して静的なチルトおよびズームの方向を設定できます。この方向は、プログラムで更新できます。 また、主点の変更などの他のオプションも使用できます。 SpeedBasedCameraBehavior
には カスタマイズオプションもあり、トラッキングモードでの使用が最適です。 -
ManeuverNotificationOptions
では、 TTS 音声コマンドをいつ転送するかを指定できます。
マップ ビュー のカスタマイズオプションがさらに必要な場合 は、VisualNavigator
の代わりに Navigator
を使用することを検討してください。 ヘッドレスなNavigator
であれば、同じ機能を利用できます。 ただし、デフォルトまたはカスタマイズ可能なレンダリングオプションはありません。その代わりに、マップ ビュー 全体を独自にレンダリングできます。たとえば、より大きなルートラインやその他の視覚的なカスタマイズを使用する場合は、 HERE SDK の一般的なレンダリング機能を使用できます。
Navigator
を使用している場合、スムーズなマップエクスペリエンスをレンダリングするには、マップビューの現在のターゲット位置を自分で更新する必要があります。 ロケーションプロバイダは、新しい位置情報の更新を個別の手順でのみ送信します。これは、高頻度で配達された場合でも、「ジャンプ」マップ ビュー につながります。 そのため、 InterpolatedLocationDelegate
を使用して、VisualNavigator
と同じスムーズな位置更新を取得することをお勧めします。
ルートの飲食
デフォルト では、VisualNavigator
は異なる色でRoute
をレンダリングし、現在の位置の背後にある移動パーツをユーザーの前のパーツから視覚的に分離します。 これは無効化またはカスタマイズできます。 既定では、 HERE Wego モバイルアプリケーションと同じ色が使用されます。
通過済みのルートの視覚化を無効にする場合は、次を呼び出してください。
visualNavigator.isRouteProgressVisible = false
デフォルト VisualNavigatorColors
では、昼間モードと夜間モードが使用できます。 たとえば、日中に応じて色を切り替えることができます。 デフォルトの色は、次のようにカスタマイズできます。
private func customizeVisualNavigatorColors() {
let routeAheadColor = UIColor.blue
let routeBehindColor = UIColor.red
let routeAheadOutlineColor = UIColor.yellow
let routeBehindOutlineColor = UIColor.gray
let maneuverArrowColor = UIColor.green
let visualNavigatorColors = VisualNavigatorColors.dayColors()
let routeProgressColors = RouteProgressColors(
ahead: routeAheadColor,
behind: routeBehindColor,
outlineAhead: routeAheadOutlineColor,
outlineBehind: routeBehindOutlineColor
)
visualNavigatorColors.maneuverArrowColor = maneuverArrowColor
visualNavigatorColors.setRouteProgressColors(sectionTransportMode: SectionTransportMode.car, routeProgressColors: routeProgressColors)
visualNavigator?.colors = visualNavigatorColors
}
これ により、パスに沿ってレンダリングされる操作矢印の色を変更して、次のターンを示すこともできます。
経由地イベントを受信します
VisualNavigator
/ Navigator
classes は、より便利な通知を提供します。 次に、渡されたウェイポイントで通知を受け取る方法の例を示します。 目的地のウェイポイントでは、次の 2 つの方法で通知を受け取ることができます。
- 以下の最初の代理人が目的地に到着したことを通知します。そのため、ナビゲーションを停止できます。
- 一方、次の 2 番目のデリゲートは 、宛先経由地 を含むすべてのタイプの経由地 について通知を受け取る方法を示し ていますが、パススルー経由地 は含まれていません。
func onDestinationReached() {
showMessage("Destination reached.")
}
func onMilestoneStatusUpdated(milestone: Milestone, status: MilestoneStatus) {
if milestone.waypointIndex != nil && status == MilestoneStatus.reached {
print("A user-defined waypoint was reached, index of waypoint: \(String(describing: milestone.waypointIndex))")
print("Original coordinates: \(String(describing: milestone.originalCoordinates))")
} else if milestone.waypointIndex != nil && status == MilestoneStatus.missed {
print("A user-defined waypoint was missed, index of waypoint: \(String(describing: milestone.waypointIndex))")
print("Original coordinates: \(String(describing: milestone.originalCoordinates))")
} else if milestone.waypointIndex == nil && status == MilestoneStatus.reached {
print("A system-defined waypoint was reached, index of waypoint: \(String(describing: milestone.mapMatchedCoordinates))")
} else if milestone.waypointIndex == nil && status == MilestoneStatus.missed {
print("A system-defined waypoint was missed, index of waypoint: \(String(describing: milestone.mapMatchedCoordinates))")
}
}
このメソッド onMilestoneStatusUpdated()
は 、ルートに沿って渡された、または失われたウェイポイントに関する情報を含むインスタンスMilestone
を提供します。 ストップオーバー のウェイポイントのみが含まれています。 また、目的地のウェイポイントと、ユーザーが追加したその他のすべてのストップオーバーウェイポイントが含まれます。 さらに、 HERE SDK が追加したウェイポイントも含まれています。たとえば、フェリーを利用する必要がある場合などです。 ただし、旅程の出発地点である最初のウェイポイントは除外されます。 パス スルータイプのウェイポイント も除外されます。
Milestone
には、ルートの計算時にユーザーが設定したウェイポイントリストを参照するインデックスが含まれています。 利用できない場合、 Milestone
は ルートの計算中に設定されたウェイポイントを参照します。たとえば、フェリーを利用する必要があることを示すために、ルーティングアルゴリズムによって追加のストップオーバーが含まれていた場合などです。
MilestoneStatus
列挙型 (enum) は、対応する Milestone
に達したか、または不在であったかを示します。
制限速度のイベントを受信します
SpeedLimitDelegate
を実装すると 、道路で利用できる制限速度でイベントを受信できます。 これらは、ローカルの標識に示されている制限速度、および特定の気象条件にのみ有効な制限速度などの特殊な速度状況に関する警告になります。
条件付きとしてマークされている制限速度は、時間によって異なる場合があります。 たとえば、学校区の制限速度は、特定の時間帯にのみ有効です。 この場合、 HERE SDK はデバイスの時間を制限速度の時間範囲と比較します。 制限速度が現在有効な場合、イベントとして伝播されます。有効でない場合は、イベントとして伝播されません。
実装例については 、 GitHub にあるナビゲーションの例アプリ を参照してください。
func onSpeedLimitUpdated(_ speedLimit: SpeedLimit) {
let speedLimit = getCurrentSpeedLimit(speedLimit)
if speedLimit == nil {
print("Warning: Speed limits unknown, data could not be retrieved.")
} else if speedLimit == 0 {
print("No speed limits on this road! Drive as fast as you feel safe ...")
} else {
print("Current speed limit (m/s): \(String(describing: speedLimit))")
}
}
private func getCurrentSpeedLimit(_ speedLimit: SpeedLimit) -> Double? {
print("speedLimitInMetersPerSecond: \(String(describing: speedLimit.speedLimitInMetersPerSecond))")
print("schoolZoneSpeedLimitInMetersPerSecond: \(String(describing: speedLimit.schoolZoneSpeedLimitInMetersPerSecond))")
print("timeDependentSpeedLimitInMetersPerSecond: \(String(describing: speedLimit.timeDependentSpeedLimitInMetersPerSecond))")
print("advisorySpeedLimitInMetersPerSecond: \(String(describing: speedLimit.advisorySpeedLimitInMetersPerSecond))")
print("fogSpeedLimitInMetersPerSecond: \(String(describing: speedLimit.fogSpeedLimitInMetersPerSecond))")
print("rainSpeedLimitInMetersPerSecond: \(String(describing: speedLimit.rainSpeedLimitInMetersPerSecond))")
print("snowSpeedLimitInMetersPerSecond: \(String(describing: speedLimit.snowSpeedLimitInMetersPerSecond))")
return speedLimit.effectiveSpeedLimitInMetersPerSecond()
}
制限速度は、指定したトランスポートモードによって異なります。 現在、 HERE SDK は 、各国の商用車に関する法的規制( CVR )に基づいて、乗用車とトラックの差別化を図っています。 つまり、上記 SpeedLimit
のイベントはトラックの制限速度の低下を示している可能性があります。 たとえば、高速道路では 、制限速度はドイツ で最大 80 km/時 になります。一方、車両では、制限速度が 130 km/時 以上であることが示されている場合があります。 CVR の制限速度を取得するには、マップバージョン 32 以降を使用してください。 それより低いマップバージョンでは、トラックは車と同じ制限速度を受け取ります。 マップのバージョンは、ダウンロードされた地域がない場合でもMapUpdater
で更新できます。ナビゲーションは、現在地図キャッシュに保存されているのと同じバージョンのマップ データ のみを要求するためです。 したがって、これはオンライン とオフラインの両方の使用に適用されることに注意してください。
情報
トラックの場合は、 RouteOptions
の内側もTruckSpecifications
を指定することをお勧めします。 トラック grossWeightInKilograms
の制限速度に影響が出る可能性があります。 ほとんどの国では、法的に許可されている制限速度に影響があります。 重量が設定されていない場合、法的に許容されているトラックの最高速度制限のみが転送されます。 HERE SDK は、トラックの重量が非常に少ないと想定します。 トラックの制限速度は、地域の商用車規制( CVR )に基づいて決定されます。 日本 のような国々では、この規制が異なります。 ただし、トラック用に計算されたルートでは、車両に適した制限速度は提供されません。たとえば、トラックの重量が 3.5 T 未満の場合は、代わりに車のルートを計算することを検討してください。
注意 : トラック 運転者の場合、トラッキングモードの場合は、navigator.trackingTransportProfile(vehicleProfile: vehicleProfile)
を呼び出しVehicleProfile
てトランスポートモードtruck
などを使用して設定します。 デフォルト car
では、が想定され、車両に有効な制限速度のみを受信します。車両に応じて、重量などの他の車両プロパティも指定してください。
注
日本 のルートの場合、TruckSpecifications
経由で特殊フラグisLightTruck
を設定できます。 このフラグは、トラックが車両として分類できるほど軽量であるかどうかを示します。 このフラグ は、日本 以外の国では使用できません。 これはこのフィーチャーのベータ版です。
速度警告イベントを受信します
新しい制限速度イベント ( 上記を参照 ) を受信したときに、自分で制限速度を超過したことを検出できますが、アプリに速度警告フィーチャーを実装するのに役立つ、より便利なソリューションがあります。
注
これは、天候に応じた制限速度などの一時的な制限速度を超過した場合には警告しません。
onSpeedWarningStatusChanged()
ドライバーが現在許可されている制限速度を超えるとただちに通知されます。 また、制限速度を超過した後、ドライバーが再び低速で走行しているときにも通知されます。
func onSpeedWarningStatusChanged(_ status: SpeedWarningStatus) {
if status == SpeedWarningStatus.speedLimitExceeded {
AudioServicesPlaySystemSound(SystemSoundID(1016))
}
if status == SpeedWarningStatus.speedLimitRestored {
print("Driver is again slower than current speed limit (plus an optional offset).")
}
}
注
onSpeedWarningStatusChanged()
では、制限速度データが利用できない場合は通知されません。 この情報は NavigableLocation
、インスタンスの一部としてのみ使用できます。
SpeedWarningStatus
が 通知されるのは、現在の速度を超過した場合、または再び復元された場合のみです。たとえば、ドライバーが頻繁に運転する速度が速すぎた場合、 1 つのイベントのみが通知されます。
onSpeedWarningStatusChanged()
現在の道路の制限速度およびドライバーの速度に応じて通知します。 つまり、ルートから独立して、速度警告イベントを追跡モードでも取得できます。 その結果 speedLimitRestored
、ルートが変更されたときに、再び低速走行した後でイベントを受け取ることができます。
オプションで、制限速度の値に追加されるオフセットを定義できます。 オフセットを含む制限速度を超過した場合にのみ、通知が送られます。 以下では、 2 つのオフセットを定義します。 1 つは、より低い方のオフセット、もう 1 つはより高速な制限のためのオフセットです。 境界は highSpeedBoundaryInMetersPerSecond
次の要素で定義されます。
private func setupSpeedWarnings() {
let speedLimitOffset = SpeedLimitOffset(lowSpeedOffsetInMetersPerSecond: 2,
highSpeedOffsetInMetersPerSecond: 4,
highSpeedBoundaryInMetersPerSecond: 25)
visualNavigator.speedWarningOptions = SpeedWarningOptions(speedLimitOffset: speedLimitOffset)
}
ここでは、highSpeedBoundaryInMetersPerSecond
を 25 m/s に設定しています。 制限速度の標識に 25 m/s を超える値が表示 されている場合、使用されているオフセットはhighSpeedOffsetInMetersPerSecond
です。 25 m/s 未満の場合、使用されているオフセットは lowSpeedOffsetInMetersPerSecond
です。
上で使用した値の例では、
-
道路の制限速度が 27 m/s の場合、使用される(高速)オフセットは 4 m/s です これは、 31 m/s = 27 m/s + 4 m/s を超える速度で走行している場合にのみ警告通知を受け取ることを意味します highSpeedOffsetInMetersPerSecond
現在の制限速度がより大きいため、 highSpeedBoundaryInMetersPerSecond
が使用されます。
-
道路の制限速度が 20 m/s の場合、使用されている(低速)オフセットは 2 m/s です つまり、 22 m/s = 20 m/s + 2 m/s を超える速度で走行している場合にのみ、警告通知が送られます lowSpeedOffsetInMetersPerSecond
現在の制限速度がよりも小さいため、 highSpeedBoundaryInMetersPerSecond
が使用されます。
負のオフセット値も設定できます。 これは、制限に達する前にバッファを用意して制限速度を超過しないようにする場合に役立ちます。 走行 速度が遅すぎる場合、例えば定義されているオフセットよりも遅い場合などは、前の速度警告が復元されない限り、通知を受け取ることはありません。
注
車両の仕様については、上記の制限速度についての規則と同じ規則が適用されます。
スピードカメライベントを受信します
Navigator
またはVisualNavigator
にSafetyCameraWarningDelegate
を接続すると、ドライバーの速度を検知するカメラに通知するSafetyCameraWarning
イベントについて通知を受け取ることができます。
ほとんどの国では、カメラは固定的にインストールされています。 HERE SDK は、カメラが現在アクティブかどうかを通知しません。
「スピードカメラ」とも呼ばれるセイフティカメラに関する通知を受け取ることは、国によっては利用できない場合があります。地域の法律および規制によります。 フランスなどの国では、スピードカメラの正確な位置情報は法律で禁止されています。 代わりに、政府のガイドラインを満たすためには、 ここでの通知の精度を下げることのみができます。 ただし、ほとんどの国では、正確な位置情報が許可されています。
現在、以下の国々がサポートされています。
スピードカメラのカバレッジ
- アメリカ合衆国
- イギリスのイギリスと北アイルランド
- アラブ首長国連邦
- トルコ
- タイ
- 台湾
- スウェーデン
- スペイン
- 南アフリカ
- スロベニア
- スロバキア
- シンガポール
- セルビア
- サウジアラビア
- ロシア連邦
- ルーマニア
- カタール
- ポルトガル
- ポーランド
- オマーン
- ノルウェー
- オランダ
- メキシコ
- マレーシア
- マカオ
- ルクセンブルグ
- リトアニア
- ラトビア
- クウェート
- カザフスタン
- イタリア
- イスラエル
- マン島
- アイスランド
- ハンガリー
- 香港
- ギリシャ
- フランス
- フィンランド
- エストニア
- デンマーク
- チェコ
- キプロス
- クロアチア
- チリ
- カナダ
- ブルガリア
- ブラジル
- ボスニア・ヘルツェゴビナ
- ベルギー
- ベラルーシ
- バーレーン
- アゼルバイジャン
- オーストリア
- アルゼンチン
- アンドラ
道路の属性を取得します
RoadAttributesDelegate
を実装すると、道路属性でイベントを受信できます。 道路を走行中に属性が変更されると、イベントが開始されます。
func onRoadAttributesUpdated(_ roadAttributes: RoadAttributes) {
print("Received road attributes update.")
if (roadAttributes.isBridge) {
print("Road attributes: This is a bridge.")
}
if (roadAttributes.isControlledAccess) {
print("Road attributes: This is a controlled access road.")
}
if (roadAttributes.isDirtRoad) {
print("Road attributes: This is a dirt road.")
}
if (roadAttributes.isDividedRoad) {
print("Road attributes: This is a divided road.")
}
if (roadAttributes.isNoThrough) {
print("Road attributes: This is a no through road.")
}
if (roadAttributes.isPrivate) {
print("Road attributes: This is a private road.")
}
if (roadAttributes.isRamp) {
print("Road attributes: This is a ramp.")
}
if (roadAttributes.isRightDrivingSide) {
print("Road attributes: isRightDrivingSide = \(roadAttributes.isRightDrivingSide)")
}
if (roadAttributes.isRoundabout) {
print("Road attributes: This is a roundabout.")
}
if (roadAttributes.isTollway) {
print("Road attributes change: This is a road with toll costs.")
}
if (roadAttributes.isTunnel) {
print("Road attributes: This is a tunnel.")
}
}
実装例について は、 GitHub にあるナビゲーションの例アプリを参照してください。
HERE SDK 自体は、このようなイベントには反応しませ roadAttributes.isTunnel
ん。 アプリケーションは isTunnel
、 true である限り夜間マップ スキーム に切り替えることを決定できます。 内部的には、 HERE SDK はトンネル補間アルゴリズムを使用してこの検出を提供しています。通常、 GPS 信号は非常に弱いか、トンネルにいる間に失われる可能性があります。
レーンアシスタンスを利用できます
HERE SDK は、ドライバーがルートの走行を助けるために車線変更を提供します。 「いいえ Route
」に設定されている場合、車線支援は提供されません。
ジャンクションに達する前に、 2 人の独立した受講者を設定して、次のイベントを取得できます ( 交差点およびロータリーを含む ) 。
-
ManeuverViewLaneAssistance
: Lane
ジャンクションが複雑と見なされているかどうかにかかわらず、ジャンクションで次のルート操作が行われた場合の推奨事項のリストを提供します。 -
JunctionViewLaneAssistance
: Lane
ジャンクションで操作が行われたかどうかにかかわらず、複雑なジャンクションでのみ推奨事項のリストを提供します。 このイベントは、非複合ジャンクションには配信されません。
複合ジャンクションは次のように定義されます。
- ジャンクションには少なくとも分岐があります。
- ジャンクションには、現在のルートに沿っていない方向のレーンが少なくとも 2 つあります。
両方のイベントを同じジャンクションまたは異なるジャンクションに送信できます。 Lane
インスタンスには、現在の道路で利用可能な車線、その方向のカテゴリ、車線が推奨されるかどうかなどの情報が含まれています。
どちらのイベントも、高速道路以外のジャンクションより 300 メートル先、高速道路のジャンクションより 1300 メートル先に発生します。 ただし、現在のところ、次の複合ジャンクションまでの距離は JunctionViewLaneAssistance
イベントの一部として公開されていません。 ManeuverViewLaneAssistance
では、 この距離は、RouteProgress
イベント経由で利用できる次の操作までの距離の一部として利用できます。
各車線は、以下 LaneDirectionCategory
に保存されている複数の方向に進むことができます。
-
straight
: 直進する車線。 -
slightlyLeft
: 45 度前後にわずかに左に出る車線。 -
slightlyRight
: 45 度前後にわずかに右に曲がる車線。 -
quiteLeft
: 90 度前後にかなり左に出る車線。 -
quiteRight
: 90 度前後の車線。 -
hardLeft
: 135 度ほど左に曲がる車線。 -
hardRight
: 135 度前後に急に曲がる車線。 -
uTurnLeft
: 左に U ターンして 180 度曲がる車線。 -
uTurnRight
: 右に U ターンして 180 度曲がる車線。
すべてのメンバーが 同時にtrue
または false
にできることに注意してください。 理論 的には、すべてのメンバーが車線がすべての複数の方向に導かれる場合にtrue
になることがあります。 ただし、ほとんどの車線は 1 つまたは 2 つの方向につながっており、たとえば、車線が 2 つの別々の車線に分かれた場合、quiteLeft
と quiteRight
は true
になります。
ドライバーに視覚的なフィードバックを提供するには、 9 つの方向ごとに 1 つの透明なイメージアセットを作成することをお勧めします。 各画像をオーバーレイとして使用し、複数の画像を 1 つの車線のピクトグラムに混合して、道路上の車線ごとに可能な道順を示すことができます。
最も重要なのは、車両がルートを走行している間に、どの車線を走行するかドライバーに知らせることができることです。 この情報はLane.recommendationState
に保存 され、推奨レーンの絵文字を強調表示することをお勧めします。
図 : 3 つのレーンがある道路で、左端の 2 つの道路が次の操作につながる可能性のある視覚化の例。 レーンアシスタンス情報 には、逆方向のレーンは含まれていません。代わりに、現在の走行方向のレーンのみが記述されています。 レーンのリストは、常に左端のレーン(インデックス 0 )から道路の右端のレーン(最後のインデックス)まで並べ替えられます。
このように、レーンアシスタンスは、左側および右側の両方の運転国で同じように機能します。
注
左側の運転国にいるかをroadAttributes.isRightDrivingSide
で確認してください。 操縦指示およびその他の通知は、自動的に国に合わせて調整されます。 レーンアシスタンスの場合、国に関係なくコードは同じように機能します。レーンのリストは常に左からインデックス 0 から右に並べ替えられます。
ManeuverViewLaneAssistance
イベントを受信した直後にイベントを表示することをお勧めします。 音声 ManeuverNotificationDelegate
ガイダンスイベントを受信するために、イベントがと同期されます。
JunctionViewLaneAssistance
イベントによって提供された車線情報は、別の UI エリアに表示することをお勧めします。これは、今後注意が必要な複雑な交差点があることを示しています。
ManeuverViewLaneAssistance を利用して、ジャンクションでの操縦について推奨される車線を取得できます
このイベントManeuverViewLaneAssistance
では、操作が行われるジャンクションで推奨レーンが提供されます。 この操作は、 VisualNavigator
が MapView
をレンダリングしているときに、マップ上で操作矢印によって表示されます。ジャンクションの場所は、RouteProgress
イベントの一部として利用できる次のManeuver
ジャンクションから取得できます。
各 ManeuverViewLaneAssistance
イベントは、ManeuverNotificationDelegate
によって送信された対応する操作音声通知と同期されます。 これは、ほとんどの道路で、交差点までの距離で次の操作を説明する操作音声通知テキストと同じ頻度で、イベントが同時に到着することを意味します。 以下で説明するように、このイベントは、 TTS エンジンが操作メッセージをドライバーに伝えるために使用できます。
上記の他のイベントと同様に、Navigator
またはVisualNavigator
にManeuverViewLaneAssistanceDelegate
を添付できます。 結果 ManeuverViewLaneAssistance
のオブジェクトには、現在の道路で利用可能な車線に関する情報と、その道順などの情報が含まれます。
次のコード スニペットは、どのレーンを取得するかについての情報を取得する方法を示しています。
func onLaneAssistanceUpdated(_ laneAssistance: ManeuverViewLaneAssistance) {
let lanes = laneAssistance.lanesForNextManeuver
logLaneRecommendations(lanes)
let nextLanes = laneAssistance.lanesForNextNextManeuver
if !nextLanes.isEmpty {
print("Attention, the next next maneuver is very close.")
print("Please take the following lane(s) after the next maneuver: ")
logLaneRecommendations(nextLanes)
}
}
private func logLaneRecommendations(_ lanes: [Lane]) {
var laneNumber = 0
for lane in lanes {
if lane.recommendationState == .recommended {
print("Lane \(laneNumber) leads to next maneuver, but not to the next next maneuver.")
}
if lane.recommendationState == .highlyRecommended {
print("Lane \(laneNumber) leads to next maneuver and eventually to the next next maneuver.")
}
if lane.recommendationState == .notRecommended {
print("Do not take lane \(laneNumber) to follow the route.")
}
logLaneDetails(laneNumber, lane)
laneNumber += 1
}
}
func logLaneDetails(_ laneNumber: Int, _ lane: Lane) {
let laneDirectionCategory = lane.directionCategory
print("Directions for lane \(laneNumber):")
print("laneDirectionCategory.straight: \(laneDirectionCategory.straight)")
print("laneDirectionCategory.slightlyLeft: \(laneDirectionCategory.slightlyLeft)")
print("laneDirectionCategory.quiteLeft: \(laneDirectionCategory.quiteLeft)")
print("laneDirectionCategory.hardLeft: \(laneDirectionCategory.hardLeft)")
print("laneDirectionCategory.uTurnLeft: \(laneDirectionCategory.uTurnLeft)")
print("laneDirectionCategory.slightlyRight: \(laneDirectionCategory.slightlyRight)")
print("laneDirectionCategory.quiteRight: \(laneDirectionCategory.quiteRight)")
print("laneDirectionCategory.hardRight: \(laneDirectionCategory.hardRight)")
print("laneDirectionCategory.uTurnRight: \(laneDirectionCategory.uTurnRight)")
_ = lane.type
_ = lane.access
}
laneAssistance.lanesForNextNextManeuver
は、通常空のリストですが、 2 つの操作が非常に近い場合があります。 このような場合、このリストには、現在の操作状況に達した直後に車線が取得する情報が保持されます。
次の操作に達するまで、車線に関する情報が有効になります。 次の操作に到達するか、または新しい ManeuverViewLaneAssistance
イベントに含まれている情報に置き換えられたら、非表示にする必要があります。
if previousManeuverIndex != nextManeuverIndex {
}
上記のコードRouteProgressDelegate
を参照 すると、nextManeuverIndex
の入手方法を確認できます。この方法では、新しい操作を行う必要があることが示されます。
JunctionViewLaneAssistance で、複合ジャンクションのレーンに関する推奨事項を入手できます
HERE SDK は、ManeuverViewLaneAssistance
(上記を参照)に加えて、ジャンクションで実際に操作が行われていない場合でも、複雑なジャンクションで利用可能なレーンについて通知するイベント JunctionViewLaneAssistance
を提供します。 これらの通知は ManeuverViewLaneAssistance
と並行して動作しますが 複雑 なジャンクションに達する前にのみ発生します ( 上記を参照 ) 。
ManeuverViewLaneAssistance
と比較して、このJunctionViewLaneAssistance
イベントでは、複雑なジャンクションを安全に通過するためにより多くのレーンを推奨できますが、ジャンクションを通過した後、これらのレーンのすべてが次の操作につながるわけではありません。
ManeuverViewLaneAssistance
とは異なり 、ジャンクションが渡されたタイミングを検出するには、リストが空かどうかを確認します。
func onLaneAssistanceUpdated(_ laneAssistance: JunctionViewLaneAssistance) {
let lanes = laneAssistance.lanesForNextJunction
if (lanes.isEmpty) {
print("You have passed the complex junction.")
} else {
print("Attention, a complex junction is ahead.")
logLaneRecommendations(lanes)
}
}
複合ジャンクションを通過したら、アプリ の UI を更新して車線情報を削除することをお勧めします。 JunctionViewLaneAssistance
イベントは、複雑な交差点でどの車線を走行するかを示す追加のヒントと見なすことができます。特に、このような交差点で操縦が行われない場合は、この情報は ManeuverViewLaneAssistance
イベントに含まれていないためです。
ルートがない場合、車線変更に関連するイベントは発生しませんので、ご注意ください。
標識や交差点表示のリアルなビューを取得できます
RealisticViewWarningDelegate
では、道路標識および複合交差点ビューの SVG 文字列データを 3D で受信できます。このイベントRealisticViewWarning
には、標識と交差点のビュー、両方の SVG データが含まれています。 この警告は 、複雑 なジャンクションにのみ表示されます(上記を参照)。
private func setupRealisticViewWarnings() {
let realisticViewWarningOptions = RealisticViewWarningOptions(aspectRatio: AspectRatio.aspectRatio3X4, darkTheme: false)
visualNavigator.realisticViewWarningOptions = realisticViewWarningOptions
visualNavigator.realisticViewWarningDelegate = self
}
func onRealisticViewWarningUpdated(_ realisticViewWarning: RealisticViewWarning) {
let distance = realisticViewWarning.distanceToRealisticViewInMeters
let distanceType: DistanceType = realisticViewWarning.distanceType
if distanceType == DistanceType.ahead {
print("A RealisticView ahead in: " + String(distance) + " meters.")
} else if distanceType == DistanceType.passed {
print("A RealisticView just passed.")
}
let realisticView = realisticViewWarning.realisticView
guard let signpostSvgImageContent = realisticView?.signpostSvgImageContent,
let junctionViewSvgImageContent = realisticView?.junctionViewSvgImageContent
else {
print("A RealisticView just passed. No SVG data delivered.")
return
}
print("signpostSvgImage: \(signpostSvgImageContent)")
print("junctionViewSvgImage: \(junctionViewSvgImageContent)")
}
realisticView.signpostSvgImageContent
は 、realisticView.junctionViewSvgImageContent
の上にオーバーレイすることを目的 としています。 両方の画像を同じ縦横比でリクエストできます。 このようにすると、両方の画像のサイズが同じになり、左上の同じ位置にレンダリングできます。
スクリーンショット : 標識の画像でオーバーレイされた交差点表示。 HERE SDK は SVG を文字列としてのみ提供 するので、サードパーティのライブラリ を使用して、 SvgView などの SVG 文字列の内容をレンダリングする必要があります。 正しいフォントを使用するために、 HERE SDK には無料のフォントパッケージが用意されています。以下を参照してください。
注
ジャンクションビューのデータは約 2 MB のみを占有するように最適化され、署名後のデータはわずか数 KB しか占有しません。 ただし、利用可能 なフィーチャー設定 を使用して、事前にイメージデータをプリロードすることをお勧め します。詳細については、最適化ガイドを参照してください。
16:9の解像度は横向きの形式で使用できますが、縦向きモードでも使用して、全画面表示ができないようにすることができます。 ただし、SVGアセットは非常に詳細なので、セカンダリディスプレイでフルスクリーンで表示することをお勧めします。
注
スピードカメラ、道路標識、現実的なビューなど、道路沿いの単一のオブジェクトについて通知する位置警告の場合、一度に発生するアクティブな警告は常に1つだけです。 これは、各 ahead
イベントの後に常に passed
イベントが続くことを意味し、1つのオブジェクトに対する2つの先行警告が同時にアクティブになることを回避します。
ナビゲーションの例、 GitHub のアプリ を参照して、使用例を確認してください。
注
このフィーチャーRealisticView
はベータリリースとしてリリースされているため、いくつかのバグや予期しない動作が発生する可能性があります。 非推奨プロセスなしで新しいリリースでは、関連するAPIが変更される可能性があります。
SVG レンダラと HERE フォントを統合します
署名者の SVG をレンダリングするに は ( 上記を参照 ) 、 SvgView プラグインを使用することをお勧めします。 さらに、 SVG コンテンツでフォントファミリとして定義されている必要な TTF フォントが必要です。 これらのフォントは、 HERE SDK 配布パッケージに含まれています。
-
SVGView
プラグインベンダーの指示に従って統合します。 ベンダーのライセンスに問題がないことを確認してください。 CocoaPods を pod 'SVGView'
プラグインと併用するか、手動で統合します。
-
import SVGView
コードにステートメントを追加し、プラグインの統合が成功したかどうかを確認します。
-
SignpostFonts.zip
HERE SDK 配布パッケージ( HERE SDK のバイナリも含むパッケージ)にあるアーカイブを展開します。 コンテンツを Xcode プロジェクトのフォルダーにコピーします。 次に、 Xcode で、左側のプロジェクトペインを右クリックし、 [ プロジェクトにファイルを追加 ] を選択します。 含める TTF フォントファイルを選択します。 これにより、フォントが自動的にターゲットに追加されます。
-
plist
ファイルを変更して、追加したフォントを指定します。
<key>UIAppFonts</key>
<array>
<string>FiraGO-Map.ttf</string>
<string>SignText-Bold.ttf</string>
<string>SignTextNarrow-Bold.ttf</string>
<string>SourceHanSansSC-Normal.ttf</string>
</array>
- SVG コンテンツをレンダリングします。
private func showRealisticViews(signpostSvgImageContent: String,
junctionViewSvgImageContent: String) {
var signpostSvgImageContent = signpostSvgImageContent
let signpostSvgImage = SVGView(string: signpostSvgImageContent)
let junctionViewSvgImage = SVGView(string: junctionViewSvgImageContent)
if (signpostSvgImage.svg == nil || junctionViewSvgImage.svg == nil) {
print("Unexpectedly, the SVG string could not be parsed.")
return
}
struct SVGUIView: View {
var junctionViewSvgImage: SVGView?
var signpostSvgImage: SVGView?
var width: CGFloat = 0
var height: CGFloat = 0
var body: some View {
ZStack {
junctionViewSvgImage
signpostSvgImage
}.frame(width: width, height: height)
}
}
var realisticView = SVGUIView()
realisticView.signpostSvgImage = signpostSvgImage
realisticView.junctionViewSvgImage = junctionViewSvgImage
realisticView.width = view.frame.size.width
realisticView.height = view.frame.size.height
let uiView = UIHostingController(rootView: realisticView).view!
}
現在、 HERE SDK では次の TTF フォントが提供されています。 これらのコードは、商用および非商用のプロジェクトで自由に使用できます。 アーカイブSignpostFonts.zip
に含まれている各フォントのライセンスファイルを確認してください。
- SourceHanSansSC-Normal.ttf : このフォントは、主にマカオ、台湾、 Hongkong で使用されます。
- FiraGO-Map.ttf : このフォントは主にイスラエルで使用されます。
- SignText - Bold.ttf : このフォントは主にベトナムで使用されます。
- SignTextNarrow - Bold .ttf : このフォントは、上記の国を除くすべての国で使用されます。
注
SVG コンテンツで指定されているフォントファミリが見つからない場合、通常は任意の SVG プラグインによってデフォルトのフォントがレンダリングされますが、期待どおりに表示されない場合があります。
環境ゾーンの警告を取得します
環境ゾーンは、 LEZ ( Low Emission Zones )または CAZ ( Clean Air Zones )とも呼ばれ、大気の質を改善し、汚染を低減するために特定の制限または規制が実施されている都市または地域内の指定地域です。 これらのゾーンは、二酸化窒素( NO2 )や粒子状物質( PM )など、高レベルの汚染物質を排出する車両の侵入を阻止または制限することを目的としています。
環境ゾーンの特定の規則および規制は、都市や国によって異なる場合があります。 通常、特定の排出ガス基準を満たしていない車両は、その地域への侵入を禁止されているか、または料金を支払う必要があります。
環境ゾーンの指定および対応する規則は、輸送機関および環境機関と協力して、地域または地方の当局によって決定されます。
HERE SDK は、次のような今後の環境ゾーンで知られています。
func onEnvironmentalZoneWarningsUpdated(_ environmentalZonesWarnings: [heresdk.EnvironmentalZoneWarning]) {
environmentalZonesWarnings.forEach { environmentalZoneWarning in
let distanceType = environmentalZoneWarning.distanceType
if distanceType == .ahead {
print("A EnvironmentalZone ahead in: \(environmentalZoneWarning.distanceInMeters) meters.")
} else if distanceType == .reached {
print("A EnvironmentalZone has been reached.")
} else if distanceType == .passed {
print("A EnvironmentalZone just passed.")
}
let name = environmentalZoneWarning.name
let description = environmentalZoneWarning.description.defaultValue
let zoneID = environmentalZoneWarning.zoneId
let websiteUrl = environmentalZoneWarning.websiteUrl
print("environmentalZoneWarning: description: \(String(describing: description))")
print("environmentalZoneWarning: name: \(name)")
print("environmentalZoneWarning: zoneID: \(zoneID)")
print("environmentalZoneWarning: websiteUrl: \(websiteUrl ?? "nil")")
}
}
EnvironmentalZoneWarningOptions
を都市部、高速道路、および地方道路タイプのデフォルトの距離通知のしきい値を変更する場合に使用します。 以下のも参照してください。
通知頻度
RouteProgress
などのすべてのイベントは、位置情報の更新に応じて送信されます。 LocationEngine
を使用する場合、 LocationAccuracy.navigation
は、少なくとも 1 秒近くの更新頻度を使用してください。
このルールの例外は、 RouteDeviation
、 RoadAttributes
、 RoadTexts
、 Milestone
、ManeuverViewLaneAssistance
、イベントなどのイベント駆動型の通知です。 各場所を更新した後、そのようなイベントを配信する必要があるかどうかを確認します。 通常、これは現在の道路で属性が変更されたときに発生します。
一部のイベントでは、経由の操作通知テキストなどのしきい値を設定でき ManeuverNotificationTimingOptions
ます。
SpeedLimit
、 SafetyCameraWarning
、 TollStop
RoadSignWarning
RealisticViewWarning
、、などの Warner の場合、通知のしきい値 ( TruckRestrictionWarning
イベントを除く、以下を参照 ) は次のとおりです。
- 都市で
AHEAD
は、 1000 メートル先にイベントが送信されます。 - 田舎道では、イベントは 1500 m 先に送られます。
-
高速道路を利用する場合は、 2000 m 先にイベントが送られます。
TruckRestrictionWarning
イベントの通知しきい値 :
-
都市では、このイベントAHEAD
は 500 メートル先に送られます。
- 田舎道では、 750 メートル先にイベントが送られます。
- 高速道路を利用する場合は、 1500 m 先にイベントが送られます。
注
トラッキングモードでは、すべての警告がサポートされます。 これは、特定のルートに沿って、または目的地に到着した後で、自由にドライブを行っている場合にも、各警告タイプのイベントを取得することを意味します。
さらに、すべての警告は 、明示的に記述されている場合を除き、ルートまたはRouteOptions
セットに固有の ものではありません ( トラックの制限速度など ) 。 たとえば、 徒歩ルートを追従している間にイベントTruckRestrictionWarning
を受け取ることができます ( 必要な場合 ) 。 一般に、警告イベントは、ナビゲーターに供給されたマップマッチングした場所に基づいて生成されます。 たとえば、歩行者ルートは、 GPS 信号の精度のために横方向を無視する他の交通モードと同様に、道路の同じ側にマップマッチングされることがよくあります。
情報
アプリケーションが特定の危険な場所について警告を発したい場合があります。 たとえば、車両の前方にある障害物までの距離を表示します。 このような場合は、 navigator.calculateRemainingDistanceInMeters(GeoCoordinates coordinates)
ルート上のユーザーの現在の位置と、そのユーザーが coordinates
前方のルートにいる場合に指定された位置との間の距離を提供する便利な方法を使用することを検討してください。 が coordinates
すでにルートの背後にある場合、またはルートにまったくない場合は null
、が返されます。 この方法では、アプリが coordinates
問題の発生先を把握している必要があります。
トラック案内
HERE SDK は、さまざまな機能を備えたプレミアムトラックの取り回しおよびガイダンスをサポートしています。 たとえば、ナビゲーション中にデリゲートを添付して、狭いトンネルなど、トラックの前方の制限について通知を受け取ることができます。 他にも、大型トラックや、トラックの重量が道路の許容重量を超える道路を通過するのに十分な高さではない橋が制限されることがあります。
次のコード スニペットを参照してください。
func onTruckRestrictionsWarningUpdated(_ restrictions: [TruckRestrictionWarning]) {
for truckRestrictionWarning in restrictions {
if truckRestrictionWarning.distanceType == DistanceType.ahead {
print("TruckRestrictionWarning ahead in \(truckRestrictionWarning.distanceInMeters) meters.")
} else if truckRestrictionWarning.distanceType == DistanceType.reached {
print("A restriction has been reached.")
} else if truckRestrictionWarning.distanceType == DistanceType.passed {
print("A restriction was just passed.")
}
if truckRestrictionWarning.weightRestriction != nil {
let type = truckRestrictionWarning.weightRestriction!.type
let value = truckRestrictionWarning.weightRestriction!.valueInKilograms
print("TruckRestriction for weight (kg): \(type): \(value)")
} else if truckRestrictionWarning.dimensionRestriction != nil {
let type = truckRestrictionWarning.dimensionRestriction!.type
let value = truckRestrictionWarning.dimensionRestriction!.valueInCentimeters
print("TruckRestriction for dimension: \(type): \(value)")
} else {
print("TruckRestriction: General restriction - no trucks allowed.")
}
}
}
DistanceType.reached
は 、トラックの制限に達したことを通知します。 制限が渡されると、イベントの後にpassed
が渡されます。 制限に長さがない場合、 reached
はスキップ され、イベントpassed
のみが送信されます。 ahead
イベントは常に最初に送信されます。
各距離タイプの制限は、 1 回だけ正確に付与されます。 更新された距離情報をドライバーに継続的に通知する場合 RouteProgress
は、目的地までの頻繁な距離更新を含むをトラッキングすることで通知できます。
すべての制限がない場合は、一般的なトラックの制限が適用されます。 制限のタイプは、TruckRestrictionWarningType
からも参照 できます。
制限の警告を マップのMapFeatures.vehicleRestrictions
レイヤーと比較する場合、 道路の 1 つの方向にのみ有効な制限があることに注意してください。
注
nil ルート または 新しいルートを設定してガイダンスを停止すると、 ahead
通知とともに通知されたすべての制限がただちに passed
イベントになり、保留中の制限警告が消去されます。 ルートを追跡中 - ルートにないすべての制限がフィルタリングされますが、ドライバーがルートから十分に離れた( 15 メートルを超える)とただちに、現在の道路で前方にサポートされている制限が適用され、再び制限警告が表示されます。
トラックの制限に関する通知しきい値は、他の警告とわずかに異なり ます。 ここ に記載されているしきい値を確認してください。
このイベントTruckRestrictionWarning
は、前方の道路網のマップ データに基づいています。 現在設定されている内容にかかわらず、制限が適用 TransportMode
されます。
注
ルートを計算するとき に、次TruckSpecifications
を含むTruckOptions
を指定でき ます。 これは結果Route
に影響を与える可能性があります。 ただし 、TruckRestrictionWarning
イベントには影響しません。 先方のマップ データで検出されたほとんどの制限事項が転送されます。 そのため、現在の車両に関連しない制限警告をアプリケーションがフィルタリングすることは理にかなっている場合があります。 このイベントでは、トラッキングするルートがない場合にもトラッキングモードでイベントが配信されます。
トラックルートの詳細については 、「ルーティング 」セクションを参照してください。 たとえば、トラック専用のルートの計算方法を見つけることができます。 一般に、ルートに Truck
輸送タイプが含まれている場合、トラック用に最適化されます。
さらに、いくつかの回避オプションを指定して、たとえば特定の都市部を除外できます。 これはすべて、ルートが計算され てNavigator
または、VisualNavigator
に渡される前に指定できます。
以下のフィーチャーについても説明します。
- トラックの寸法などの車両の制限を指定したり、トラックが危険物を運搬している場合に、
TruckSpecifications
およびHazardousGood
リストを含むことができるように指定できます。 TruckOptions
この情報を使用して、トラックルートを形成できます。 トラックの制限事項について通知を受け取るに TruckRestrictionWarning
は、上記のようにイベントを聴いてください。 RoadAttributes
前述のように特定の音声を聞くことができます。 - トランスポートモードが
truck
に設定 されている場合、SpeedLimit
イベントは商用車の規制( CVR )制限速度を示します。これは、車両の制限速度よりも低い可能性があります。 ルートを計算するときは、RouteOptions
の内部TruckSpecifications
も指定することを検討してください。 トラッキングモードの場合 は、navigator.trackingTransportProfile(vehicleProfile: vehicleProfile)
を呼び出して、truck
トランスポートモードでVehicleProfile
を設定します。 デフォルトでは、トラッキングは、car
が想定されます。 トラックに応じて重量などの他の車両プロパティを必ず指定してください。 - 特に
grossWeightInKilograms
と weightInKilograms
は、ルートの制限、到着予定時刻に影響があるだけでなく、CVR の制限速度にも影響があります。 適切に設定しないと TruckSpecifications
、ルートおよび通知が適切でない可能性があります。 AvoidanceOptions
を使用して、排出ゾーンを除外して、良識ある都心部の空気を汚染しないようにすることができます。この機能を使用 すると、特定の類似RoadFeatures
のトンネルを回避することもできます。 これらはTruckOptions
経由で設定でき、ルート計算から除外されます。 - マップにスピードカメラのアイコンを表示するマップ レイヤースキームを有効にできます:
MapScene.Layers.safetyCameras
。注 : このレイヤーは車にも適しています。 - トラック固有の情報をマップに表示するように最適化されたマップ レイヤー スキームを有効にできます:
MapScene.Layers.vehicleRestrictions
。 たとえば、 影響を受ける道路上でアクティブおよび 非アクティブな制限を紫色の線で強調表示するための いくつかのMapFeatureModes
が提供されます。灰色の線または灰色のアイコンは、制限が非アクティブであることを示します。 道路がこのような紫の線を横切っており、その道路自体が紫で示されていない場合、この制限は現在の道路には適用されません。 アイコンが正確な場所を示すとは限りません。 たとえば、制限された道路の場合、アイコンが制限された道路の中央に配置されます。または、制限がより長い場合は、 1 つ以上の道路に沿って同じ制限についてアイコンを複数回繰り返すことができます。 アイコン自体は国ごとにローカライズされ、制限のタイプを表します。 ほとんどの制限では、制限の場所と種類も TruckRestrictionWarning
イベントによって示されます ( 上図を参照 ) 。 Place
の Details
にシャワーやトイレの情報が含まれている TruckAmenities
を使用します。ルート沿いの廊下を探して、トラックのアメニティが入っている場所がないか確認してください。 この機能を有効にするには、"show"
を name
として、 "truck"
を value
として指定して searchEngine.setCustomOption()
を呼び出します。
MapScene.Layers.vehicleRestrictions オフロードガイダンス
オフロードガイダンスを利用すると、オフロードの目的地に到着するのを支援できます。 通常は、マップに一致する目的地でガイダンスが停止します。 目的地が休息地の中央にある場合など、目的地が道路ネットワークにマップマッチングできない場合、目的地はオフロードと見なされます。
スクリーンショット : オフロードガイダンス 目的地がオフロードかどうかを検出し、マップに一致する目的地に到達したときにユーザーに通知できます。
func onDestinationReached() {
guard let lastSection = lastCalculatedRoute?.sections.last else {
return
}
if lastSection.arrivalPlace.isOffRoad() {
print("End of navigable route reached.")
let message1 = "Your destination is off-road."
let message2 = "Follow the dashed line with caution."
uiCallback?.onManeuverEvent(action: ManeuverAction.arrive,
message1: message1,
message2: message2)
} else {
print("Destination reached.")
let distanceText = "0 m"
let message = "You have reached your destination."
uiCallback?.onManeuverEvent(action: ManeuverAction.arrive,
message1: distanceText,
message2: message)
}
}
この例では、ビューを更新するために、アプリ側の uiCallback
メカニズムを使用します。 このコードは こことは関係がないため、省略されています。 このドキュメントは、 GitHub の「 Rerouting のExample アプリ」に記載されています。
マップと一致する目的地(たとえば、前方車両につながる道路) に達していない場合、ユーザーはオフロードガイダンスを受けられません。 オフロードガイダンスは、 onDestinationReached()
イベントの受信後にのみ開始されます。
注
オフロードイベントが開始されると、 新しいルートが設定されていない限り、通常のガイダンスモードに戻ってイベントRouteProgress
を受信する方法はありません。
オフロード走行先にガイダンスを提供するには、次のコードを追加します。
func onOffRoadProgressUpdated(_ offRoadProgress: heresdk.OffRoadProgress) {
let distanceText = convertDistance(meters: offRoadProgress.remainingDistanceInMeters)
let message = "Direction of your destination: \(round(offRoadProgress.bearingInDegrees))°"
uiCallback?.onManeuverEvent(action: ManeuverAction.arrive,
message1: distanceText,
message2: message)
}
func onOffRoadDestinationReached() {
print("Off-road destination reached.")
let distanceText = "0 m"
let message = "You have reached your off-road destination."
uiCallback?.onManeuverEvent(action: ManeuverAction.arrive,
message1: distanceText,
message2: message)
}
この例では、アプリサイドの convertDistance()
のメソッドを使用して、距離をメートルおよびキロメートルに変換します。 このコードは HERE SDK での使用には適していません。したがって、このコードの実装は上記では省略されています。
オフロードガイダンスでは、ユーザーが地図に一致する目的地に到着する前に支援を提供するものではありません。 また、 ユーザーが道路から逸脱したり、不明な道路を走行したりした場合など、走行中のオフロード走行はサポートされません。 ユーザーが既知の道路ネットワークで到達可能なルートの最後の地点に到達した場合にのみ、オフロードガイダンスが開始されます。
デフォルトでは、上記のコードがない場合でも、オフロード目的地につながる破線がマップに表示されます。 これは次のように制御できます。
visualNavigator.isOffRoadDestinationVisible = true
注
このフィーチャーは 、ユーザーを経路に沿って案内するものではなく、何らかの操作情報を提供するものでもありません。 提供された情報は慎重に取り扱うようにしてください。 ユーザーの現在位置からオフロード目的地まで直線のみが引かれます。 現実には、目的地が到達不能であるか、歩行者が移動できない危険な地域にある可能性があります。 ユーザーに適宜通知してください。
位置情報プロバイダを実装します
に Location
インスタンスを提供するには、ロケーションプロバイダが必要 VisualNavigator
です。 任意のソースから位置データをフィードできます。 HERE では、デバイスからのネイティブの位置データ と テストドライブのシミュレートされた位置データを切り替えることができる実装を使用する予定です。
すでに説明したように、 VisualNavigator
は LocationDelegate
プロトコルに準拠しているため、呼び出した onLocationUpdated(location:)
クラスのデリゲートとして使用できます。
位置情報データのソースとして、「 位置情報を検索 」セクションに示されているコードに基づいたHEREPositioningProvider
を使用します。
注
ナビゲーションでは LocationAccuracy.navigation
、 LocationEngine
ターン・バイ・ターンナビ (矢印ナビ)中に最良の結果が保証されるように、の開始時にを使用することをお勧めします。
イベントを配信するには、herePositioningProvider
を開始する必要があります 。
herePositioningProvider.startLocating(locationDelegate: visualNavigator,
accuracy: .navigation)
必要な HERE SDKの Location
タイプには、ベアリングおよび速度情報、現在の地理座標、 VisualNavigator
によって消費されるその他の情報が含まれます。 提供されたデータの正確性と完全性が高いほど、ナビゲーション全体の操作性がより正確になります。
Location
オブジェクトから取得されたbearing
値によって 移動の方向が決まり 、 その方向に回転するLocationIndicator
アセットによって示されます。 ユーザーが移動していない場合、新しいベアリング値が設定されるまで最後のローテーション値が保持されます。 Location
データのソースに応じて、この値の精度を増減できます。
内部的には 、Location
のtimestamp
が使用され、ユーザーがトンネルを通過しているか、または信号が単に失われたかなどを評価します。
GitHub で、ロケーションプロバイダのリファレンス実装を見つける ことができます。
位置シミュレータを設定します
開発中に、テスト目的でルート上で予想される進行状況を再生すると便利な場合があります。 は LocationSimulator
、元のルート座標から取得された連続的な位置情報を提供します。
以下では、 LocationSimulator
を代替プロバイダとして統合し、実際の位置情報の更新とシミュレートされた位置情報の切り替えを可能にしています。
import heresdk
class HEREPositioningSimulator {
private var locationSimulator: LocationSimulator?
func startLocating(locationDelegate: LocationDelegate, route: Route) {
if let locationSimulator = locationSimulator {
locationSimulator.stop()
}
locationSimulator = createLocationSimulator(locationDelegate: locationDelegate, route: route)
locationSimulator!.start()
}
func stopLocating() {
if locationSimulator != nil {
locationSimulator!.stop()
locationSimulator = nil
}
}
private func createLocationSimulator(locationDelegate: LocationDelegate,
route: Route) -> LocationSimulator {
let notificationIntervalInSeconds: TimeInterval = 0.5
let locationSimulatorOptions = LocationSimulatorOptions(speedFactor: 2,
notificationInterval: notificationIntervalInSeconds)
let locationSimulator: LocationSimulator
do {
try locationSimulator = LocationSimulator(route: route,
options: locationSimulatorOptions)
} catch let instantiationError {
fatalError("Failed to initialize LocationSimulator. Cause: \(instantiationError)")
}
locationSimulator.delegate = locationDelegate
locationSimulator.start()
return locationSimulator
}
}
また、LocationSimulatorOptions
を設定することで 、現在のシミュレート位置の移動速度を指定することができます。 デフォルトでは 、notificationInterval
は1で、speedFactor
は 1.0です。これは、トラフィック関連の制約を考慮せずに、ユーザが通常運転または各ルートセグメントを歩く平均速度に等しくなります。 デフォルトの速度は、道路形状、道路状況、その他の統計データによって異なる場合がありますが、現在の制限速度を超えることはありません。 値が1.0を超えると、速度が比例して増加します。 ルートに指定した時間間隔で十分な座標が含まれていない場合は、によって追加のロケーションイベントが補間 VisualNavigator
されます。
注
LocationSimulator
によって放出される位置は 補間されず、ソースに基づいて提供されます。 の場合 Route
、ルート形状の座標が使用されます(互いに非常に近い)。 の場合 GPXTrack
、座標はGPXデータに基づいて出力されます。 たとえば、2つの座標の間に100メートルのメートルがある場合、それらの2つの座標だけが時間設定に基づいて放出されます。 ただし、に入力すると VisualNavigator
、レンダリングされたマップアニメーションはによって補間 VisualNavigator
されます。
VisualNavigator
連続 Location
する更新間の距離が 100 m を超える場合、はアニメーションをスキップします が speedFactor
増加すると、ロケーションの更新間隔も変化します。通知間隔が適切に調整されていない場合は、次のようになります。 たとえば、速度係数を 8 に変更する場合は、 Location
通知間隔を 125 ms (1000 ms/8) に変更して、更新間の距離を一貫したものにする必要があります。 notificationInterval
および speedFactor
は反比例します。 したがって、 A speedFactor
が 3 の場合、 330 notificationInterval
ms を推奨します。
次のコードは 、 enableRoutePlayback(route:)
とenableDevicePositioning()
を呼び出して、シミュレートされた場所と実際の場所をシームレスに切り替える方法を示し ています。
func enableRoutePlayback(route: Route) {
herePositioningProvider.stopLocating()
herePositioningSimulator.startLocating(locationDelegate: visualNavigator, route: route)
}
func enableDevicePositioning() {
herePositioningSimulator.stopLocating()
herePositioningProvider.startLocating(locationDelegate: visualNavigator,
accuracy: .navigation)
}
新しいシミュレーションまたは実ロケーションソースを開始する前に、進行中のシミュレーションまたは実ロケーションソースを必ず停止する必要があります。
GitHub のナビゲーションサンプルアプリに含ま れている上記のコードを確認できます。
音声ガイダンス
運転中は、ユーザーの注意をルートに集中させる必要があります。 提供されている操作データから視覚的な表現を作成できますが ( 上記を参照 ) 、ターンバイターンガイダンス中に話すことを目的としたローカライズされたテキスト表現を取得することもできます。 これらの操作手順の通知 はString
として提供されるため 、任意の TTS ソリューションと一緒に使用できます。
注
操作の通知はドライバーを対象としています。 歩行者の案内には使用しないことをお勧めします。
HERE SDK には、事前に録音された音声スキンは含まれていません。 つまり、再生のために TTS エンジンを統合する必要があります。 オーディオ再生の詳細および例については、以下を参照してください。
通知の例 ( 文字列で提供 ) :
Voice message: After 1 kilometer turn left onto North Blaney Avenue.
Voice message: Now turn left.
Voice message: After 1 kilometer turn right onto Forest Avenue.
Voice message: Now turn right.
Voice message: After 400 meters turn right onto Park Avenue.
Voice message: Now turn right.
これらの通知を取得するには ManeuverNotificationDelegate
、を設定します。
visualNavigator.maneuverNotificationDelegate = self
...
func onManeuverNotification(_ text: String) {
voiceAssistant.speak(message: text)
}
HERE では、 VoiceAssistant
音声合成エンジンをラップして操作の通知を読み上げるというヘルパークラスを使用しています。 このエンジンはアップル AVSpeechSynthesizer
のクラスを使用しています。 必要に 応じて、このクラスを GitHub のナビゲーションサンプルアプリの一部として見つけることができます。
オプションで 、ナチュラルガイダンスを有効にすることもできます。 ManeuverNotification
テキストは、ルートに沿って重要なオブジェクト(信号機や停止標識など)を含めるように拡張して、操作をより理解しやすくすることができます。 例: "次 の信号で 左折してウォールストリートに入ります。" デフォルトでは、このフィーチャーは無効になっています。 これを有効にするには、 includedNaturalGuidanceTypes
のリストを介して ManeuverNotificationOptions
に trafficLight
などの NaturalGuidanceType
を少なくとも 1 つ追加します。
LanguageCode
通知テキストをローカライズするようにを設定し、 UnitSystem
メートル法 または ヤードポンド法 の長さの単位を決定するようにを設定できます。 ルートを設定する前に、必ずこの番号を呼び出してください。そうしないと、デフォルトの設定 (en-US
,metric
) が使用されます。 詳細については ManeuverNotificationOptions
、 API リファレンス を参照してください。
private func setupVoiceGuidance() {
let ttsLanguageCode = getLanguageCodeForDevice(supportedVoiceSkins: VisualNavigator.availableLanguagesForManeuverNotifications())
visualNavigator.maneuverNotificationOptions = ManeuverNotificationOptions(language: ttsLanguageCode,
unitSystem: UnitSystem.metric)
let locale = LanguageCodeConverter.getLocale(languageCode: ttsLanguageCode)
if voiceAssistant.setLanguage(locale: locale) {
print("TextToSpeech engine uses this language: \(locale)")
} else {
print("TextToSpeech engine does not support this language: \(locale)")
}
}
この例では、デバイスの希望する言語設定を使用します。 以下に、これらの情報を取得する 1 つの方法を示します。
private func getLanguageCodeForDevice(supportedVoiceSkins: [heresdk.LanguageCode]) -> LanguageCode {
let identifierForCurrenDevice = Locale.preferredLanguages.first!
var localeForCurrenDevice = Locale(identifier: identifierForCurrenDevice)
if !voiceAssistant.isLanguageAvailable(identifier: identifierForCurrenDevice) {
print("TextToSpeech engine does not support: \(identifierForCurrenDevice), falling back to en-US.")
localeForCurrenDevice = Locale(identifier: "en-US")
}
var languageCodeForCurrenDevice = LanguageCodeConverter.getLanguageCode(locale: localeForCurrenDevice)
if !supportedVoiceSkins.contains(languageCodeForCurrenDevice) {
print("No voice skins available for \(languageCodeForCurrenDevice), falling back to enUs.")
languageCodeForCurrenDevice = LanguageCode.enUs
}
return languageCodeForCurrenDevice
}
内部的 には、RouteProgress
イベントからアクセスできるManeuver
データから操作の通知テキストが生成されます。 RouteProgress
イベントは、パスした位置の更新に基づいて頻繁に生成されます。 操作の通知では、テキストメッセージを生成する頻度とタイミングを指定できます。 これは、ManeuverNotificationTimingOptions
を使用して指定できます。
各ManeuverNotificationType
について、各トランスポートモードおよび道路タイプをManeuverNotificationTimingOptions
に設定できます。 また、 距離をメートル単位 または 秒単位で指定することもできます。
-
ManeuverNotificationType.range
: 1 番目の通知。 rangeNotificationDistanceInMeters
またはrangeNotificationTimeInSeconds
を使用して指定します。 -
ManeuverNotificationType.reminder
: 2 番目の通知。 reminderNotificationDistanceInMeters
またはreminderNotificationTimeInSeconds
を使用して指定します。 -
ManeuverNotificationType.distance
: 3 番目の通知。 distanceNotificationDistanceInMeters
またはdistanceNotificationTimeInSeconds
を使用して指定します。 -
ManeuverNotificationType.action
: 4 番目の通知。 actionNotificationDistanceInMeters
またはで指定 actionNotificationTimeInSeconds
します。
タイプは距離順に並べられます。 操作の数メートル前にのみ TTS メッセージをカスタマイズする場合 は、distanceNotificationDistanceInMeters
のみを設定します。 maneuverNotificationOptions.includedNotificationTypes
経由でタイプを省略することもでき ます。 たとえば 、タイプdistance
のみを設定した場合 、操作が行われた場合でも、他の通知は受信されません (=action
) 。
以下では distance
、高速道路 ( 道路タイプ ) の車両のタイプ値 (= トランスポートモード ) のみを微調整し、その他のすべての値をそのままにします。
var carHighwayTimings =
navigator.getManeuverNotificationTimingOptions(transportMode: TransportMode.car,
roadType: RoadType.highway)
carHighwayTimings.distanceNotificationDistanceInMeters = 1500
navigator.setManeuverNotificationTimingOptions(transportMode: TransportMode.car,
roadType: RoadType.highway,
options: carHighwayTimings)
maneuverNotificationOptions.includedNotificationTypes = [
ManeuverNotificationType.range,
ManeuverNotificationType.reminder,
ManeuverNotificationType.distance,
ManeuverNotificationType.action
]
既定では、操作の通知テキストは正投影形式 ( 「ウォール街」 ) になっています。 一部の TTS エンジンは音素をサポートしており、プレーン テキスト「Wall Street」を SSML 表記法「"wɔːl"striːt」で追加します。これにより、発音がよくなります。 次のコードを呼び出して、音素を有効にします。
maneuverNotificationOptions.enablePhoneme = true
maneuverNotificationOptions.notificationFormatOption = NotificationFormatOption.ssml
音素を使用したボイスメッセージの例 :
After 300 meters turn right onto <lang xml:lang="ENG"><phoneme alphabet="nts" ph=""wɔːl"striːt" orthmode="ignorepunct">Wall Street</phoneme></lang>.
API リファレンス を参照して、 ManeuverNotificationOptions
で設定できるその他のオプションを探します。
HERE SDK は 37 言語をサポートしています。 VisualNavigator
を使用して、から言語を照会でき VisualNavigator.availableLanguagesForManeuverNotifications()
ます。 HERE SDK 内のすべての言語が LanguageCode
列挙型 (enum) として指定されます。 これを Locale
インスタンスに変換するには、LanguageCodeConverter
を使用します。 これは、 GitHub のナビゲーションサンプルアプリの一部として検索されるオープンソースのユーティリティクラスです。
注
操作の通知を生成するためにサポートされている各言語は 、 HERE SDK フレームワーク内で音声スキンとして保存されます。 フレームワークを展開し 、 VOICE_ASSETS フォルダを探します。 関心のないアセットを手動で削除して、 HERE SDK パッケージのサイズを縮小できます。
ただし、操作の通知を TTS エンジンに送信するには、選択した TTS エンジンで使用する言語がサポートされていることを確認する必要があります。 通常、各デバイスには一部の言語がプリインストールされていますが、最初はすべての言語が表示されているわけではありません。
注
SpatialAudioNavigation の例アプリでは、を VisualNavigator
iOS のネイティブコードと組み合わせて使用し、オーディオパンを使用して TTS オーディオメッセージを再生し、ステレオパノラマを介して方向を指示する方法を示します。 この例は 、 GitHub で確認できます。
音声ガイダンスでサポートされている言語
以下に 、サポートされているすべての音声言語のリストと、 HERE SDK フレームワーク内に保存されている関連する音声スキンの名前を示します。
- アラビア語(サウジアラビア): voice_package_ar-sa
- チェコ語 : voice_package_cs-cz
- デンマーク語 : voice_package_da-dk
- ドイツ語 : voice_package_de-de
- ギリシャ語 : VOICE_PACKAGE_EL-GR
- 英語 ( イギリス ) : voice_package_en-gb
- 英語(米国 ): voice_package_en-US
- スペイン語(スペイン): VOICE_PACKAGE_ES-ES
- スペイン語(メキシコ): VOICE_PACKAGE_ES-MX
- ペルシャ語(イラン料理): voice_package_fa-ir
- フィンランド語: VOICE_PACKAGE_FI
- フランス語(カナダ): voice_package_fr-CA
- フランス語 : voice_package_fr-FR
- ヘブライ語 : VOICE_PACKAGE_HE-IL
- ヒンディー語 : voice_package_hi-in
- クロアチア語 : VOICE_PACKAGE_hr-HR
- ハンガリー語 : VOICE_PACKAGE_HU-HU
- インドネシア語 : バハサ語 voice_package_id - ID
- イタリア語: voice_package_it-it
- 日本語: voice_package_ja-JP
- 韓国語 : voice_package_ko-KR
- ノルウェー語 : ブークモール語 voice_package_nb -no
- オランダ語 : voice_package_nl-nl-nl
- ポルトガル語(ポルトガル) VOICE_PACKAGE_pt
- ポルトガル語(ブラジル): VOICE_PACKAGE_pt -BR
- ポーランド語 : voice_package_pt -pt
- ルーマニア語 : voice_package_ro-R
- ロシア語 : voice_package_ru-ru
- スロバキア語 : voice_package_sk-sk
- セルビア語 : voice_package_sr-CS
- スウェーデン語 : voice_package_sv -se
- タイ語 : voice_package_th-th
- トルコ語 : VOICE_PACKAGE_tr - TR
- ウクライナ語 : VOICE_PACKAGE_UK-UA
- ベトナム語 : voice_package_vi -vn
- 中国語 ( 簡体字 ) : voice_package_zh-CN
- 中国語 ( 繁体字香港 ): voice_package_zh-HK
- 中華語(台湾語): voice_package_zh-TW
HERE SDK フレームワークを開き voice_assets
、フォルダーを検索します。 フレームワークのサイズを縮小する場合は、不要な音声パッケージを削除できます。
空間音声操作の通知
ManeuverNotificationDelegate
で提供されているものvoiceText
と同様に、空間オーディオ情報を使用して拡張することもできます ( 上記を参照 ) 。
空間オーディオの操作の通知を使用すると、音声読み上げ文字列のステレオパノラマをリアルタイムで調整できます。 これは、車両に座っているドライバーに対する操作位置に基づいています。
このため には、ManeuverNotificationDelegate
の代わりに(または並行して)SpatialManeuverNotificationDelegate
を使用します。 空間的な操作が可能になると通知をトリガーします。 さらに、 SpatialManeuverAzimuthDelegate
を追加して、 HERE SDK によって定義された空間オーディオ操作の通知軌跡の 1 つを構成する方位角エレメントをトリガーします。 結果 SpatialTrajectoryData
には、使用する次の方位角が含まれ、空間オーディオ操作の通知の軌跡が終了したかどうかが示されます。
パンニングを開始し、 SpatialManeuver
のestimatedAudioCueDuration
を更新するためにCustomPanningData
を渡し、 およびinitialAzimuthInDegrees
プロパティと sweepAzimuthInDegrees
プロパティをカスタマイズするためにSpatialManeuverAudioCuePanning
を使用します。
道路シールドアイコンを取得します
iconProvider.createRoadShieldIcon(...)
では「 A7 」や「 US-101 」などの道路番号がマップ ビューにすでに表示されているように、非同期で UIImage
を作成できます。
道路標識アイコンの作成はオフラインで行われ、インターネット接続は必要ありません。 アイコンの作成に必要なデータは、そのアイコン自体 Route
からのみ取得されますが、手動で入力することもできます。
道路標識アイコンの例。 以下では、ルートを走行している間に、データをオンザフライで取得する方法を示します。 すべての道路、特に小さな道路が道路標識アイコンで表示されるわけではありません。 一般的に、ガイダンスを開始する前、または次の操作のガイダンス中に、アイコンをルートプレビューの一部として表示して、操作が行われた場所を視覚的に示すことができます。
次の操縦と一緒に道路標識を表示しています。 道路標識アイコンを生成するために必要なすべての情報が Route
オブジェクトの一部です。
RouteType
およびLocalizedRoadNumber
などのパラメーターを必要とするアイコン自体がRoadShieldIconProperties
から生成され ます。 これらのパラメーターは、 Route
オブジェクトのSpan
から取得できます。
span.getShieldText(..)
を使用して RoadShieldIconProperties
で使用するためにshieldText
取得します。 span.roadNumbers
では、 RouteType
( レベル 1 ~ 6 の道路が主要道路かどうかを示す ) や CardinalDirection
( 「 101 West 」など ) などの追加情報を含むLocalizedRoadNumber
アイテムのリストを取得できます。
IconProvider.IconCallback
では、結果の画像またはエラーを受け取ることができます。
注
これはこのフィーチャーのベータリリースであるため、バグがいくつか発生したり、予期しない動作が発生する可能性があります。 関連する API は、非推奨プロセスなしで新しいリリースで変更されることがあります。
以下の例では 、イベントRouteProgress
で道路標識アイコンをと組み合わせて表示 / 非表示にする方法について、考えられる解決策を見つけることができます。
func onRouteProgressUpdated(_ routeProgress: heresdk.RouteProgress) {
let maneuverProgressList = routeProgress.maneuverProgress
guard let nextManeuverProgress = maneuverProgressList.first else {
print("No next maneuver available.")
return
}
let nextManeuverIndex = nextManeuverProgress.maneuverIndex
let nextManeuver = visualNavigator.getManeuver(index: nextManeuverIndex)
if previousManeuver == nextManeuver {
return;
}
previousManeuver = nextManeuver;
uiCallback?.onHideRoadShieldIcon()
guard let maneuverSpan = getSpanForManeuver(route: visualNavigator.route!,
maneuver: nextManeuver!) else {
return
}
createRoadShieldIconForSpan(maneuverSpan)
}
この例では、 ビューを更新するために、アプリ側のuiCallback
メカニズムを使用します。 このコードは ここ とは関連がないため、省略されていますが、 Rerouting
のGitHub 付属のアプリの例に記載されています。
次のような操作のためのスパンを取得できます。
private func getSpanForManeuver(route: Route, maneuver: Maneuver) -> Span? {
let index = Int(maneuver.sectionIndex)
let sectionOfManeuver = route.sections[index]
let spansInSection = sectionOfManeuver.spans
if maneuver.action == ManeuverAction.arrive {
return spansInSection.last
}
let indexOfManeuverInSection = maneuver.offset
for span in spansInSection {
let firstIndexOfSpanInSection = span.sectionPolylineOffset
if firstIndexOfSpanInSection >= indexOfManeuverInSection {
return span
}
}
return nil
}
以下に、道路シールドアイコンを生成するための情報を抽出する方法を示すコードがあります。
private func createRoadShieldIconForSpan(_ span: Span) {
guard !span.roadNumbers.items.isEmpty else {
return
}
guard var localizedRoadNumber = span.roadNumbers.items.first else {
return
}
let desiredLocale = Locale(identifier: "en_US")
for roadNumber in span.roadNumbers.items {
if roadNumber.localizedNumber.locale == desiredLocale {
localizedRoadNumber = roadNumber
break
}
}
let routeType = localizedRoadNumber.routeType
let shieldText = span.getShieldText(roadNumber: localizedRoadNumber)
let routeNumberName = localizedRoadNumber.localizedNumber.text
if lastRoadShieldText == shieldText {
return
}
lastRoadShieldText = shieldText
let countryCode = span.countryCode ?? ""
let stateCode = span.countryCode ?? ""
let roadShieldIconProperties = RoadShieldIconProperties(
routeType: routeType,
countryCode: countryCode,
stateCode: stateCode,
routeNumberName: routeNumberName,
shieldText: shieldText
)
let widthConstraintInPixels: UInt32 = ManeuverView.roadShieldDimConstraints
let heightConstraintInPixels: UInt32 = ManeuverView.roadShieldDimConstraints
iconProvider.createRoadShieldIcon(properties: roadShieldIconProperties,
mapScheme: MapScheme.normalDay,
widthConstraintInPixels: widthConstraintInPixels,
heightConstraintInPixels: heightConstraintInPixels,
callback: handleIconProviderCallback)
}
追加のフラグlastRoadShieldText
を使用して 、アイコンがすでに作成されているかどうかを確認します。
handleIconProviderCallback
次のように実装できます。
private func handleIconProviderCallback(image: UIImage?,
description: String?,
error: IconProviderError?) {
if let iconProviderError = error {
print("Cannot create road shield icon: \(iconProviderError.rawValue)")
return
}
guard let roadShieldIcon = image else {
return
}
let shieldDescription = description ?? ""
print("New road shield icon: \(shieldDescription)")
uiCallback?.onRoadShieldEvent(roadShieldIcon: roadShieldIcon)
}
ここでも、 ビューを更新するために、アプリ側のuiCallback
メカニズムを使用します。 このコードは ここ とは関連がないため、省略されていますが、 Rerouting
のGitHub 付属のアプリの例に記載されています。
ナビゲーションを停止します
route
が 設定されかつ、LocationPrivider
が開始されると、ターン・バイ・ターンナビ (矢印ナビ)が自動的に開始されますが、ナビゲーションの停止は可能なシナリオによって異なります。
ナビゲーションを停止してトラッキングモードに切り替え ( 以下を参照 ) 、パスをトラッキングしたままマップと一致する位置を受信するか、 またはトラッキングモードに戻らずにナビゲーションを停止します。 最初のケースでは、現在の route
をnil
に設定するだけで済みます。 これにより、ターン・バイ・ターンナビ (矢印ナビ)関連のすべてのイベントの伝播のみが停止されますが、マップマッチングした場所アップデートおよび速度警告情報などを受信できるように、イベントは存続します。 ターン・バイ・ターンナビ (矢印ナビ)イベントの伝播は、目的の宛先に到達すると自動的に停止されます。 route
を再度設定すると、ターン・バイ・ターンナビ (矢印ナビ)関連のすべてのイベントが再度伝播されます。
トラッキングモードに戻らずにナビゲーションを停止 する場合( たとえば、マップに一致しない位置の更新のみをロケーションプロバイダから直接取得する場合) は、VisualNavigator
からすべてのイベントを取得しないことをお勧めします。 このためには、すべての代理人をに個別に設定する必要 nil
があります。
アプリで位置情報の更新を利用するために、ロケーションプロバイダの実装を再利用できます。 HERE Positioning では、複数のインスタンスLocationDelegate
を 設定できます。
VisualNavigator
を使用する場合は、stopRendering()
を呼び出します。 MapView
が呼び出されると、VisualNavigator
によって制御されなくなります。
- マップの向き、カメラの距離、傾きなどの設定は、レンダリング中に変更された可能性がありますが、更新されなくなりました。 コール前の最後の状態
stopRendering()
が保持 されます。 たとえば、ガイダンス中にマップが傾いていた場合、マップは傾斜したままになります。 このため、stopRendering()
を呼び出した後で、目的のカメラ設定を適用することをお勧めします。 - 新しい場所を
VisualNavigator
に送り続けても、マップは現在の場所に移動されなくなり ます。 VisualNavigator
によって所有されている既定またはカスタムの位置情報インジケータが再度非表示になります。 RouteProgress
nil デリゲートを設定してサブスクライブを解除しない限り、などの位置情報に基づくすべてのイベントが配信されます ( 上記を参照 ) 。
注
は VisualNavigator
MapView
インスタンス上で動作するため、 stopRendering()
を初期化解除する前にを呼び出すことをお勧め MapView
します。 さらに、停止 LocationSimulator
することをお勧めします DynamicRoutingEngine
。 ただし、が MapView
一時停止している場合は、も停止する必要は VisualNavigator
ありません。 VisualNavigator
が MapView
一時停止すると、は自動的にレンダリングを停止し、 MapView
が再開されるとレンダリングを開始します(が VisualNavigator
以前にレンダリングされていたとき)。
トラッキング
VisualNavigator
クラスを使用してターンバイターン ナビゲーションを開始および停止することができますが、ルートをたどる必要のないトラッキングモードに切り替えることもできます。
このモードは、しばしば 運転者アシスタンスモードとも呼ばれます。 公共交通機関を除く、すべての交通手段で利用できます。 公共交通機関の利用は、トラッキングにおいてに不確かな、予期しない結果が生じる可能性があります。 他のすべてのトランスポートモードがサポートされていますが、トラッキングは車両のトランスポートモードに最も適しています。
追跡を有効にするには、次の電話番号に連絡する必要があります。
visualNavigator.route = nil
herePositioningProvider.startLocating(locationDelegate: visualNavigator,
accuracy: .navigation)
ここでは、実際の GPS 位置情報を取得できますが 、LocationSimulator
を使用して任意のルートから位置情報を再生することもできます ( 上図を参照 ) 。
もちろん、 route
インスタンスを設定せずに VisualNavigator
を初期化できます。追跡モードにのみ関心がある場合は、ルートを明示的に nil に設定する必要はありません。
注
追跡モードでは、 ルートを追跡することなく発生する可能性のある、NavigableLocationDelegate
やSpeedWarningDelegate
などの代理人のイベントのみを取得できます。 一般に、すべてのバーナーがサポートされています。 RouteProgressDelegate
ルートが設定されていない場合、などの他のデリゲートはイベントを配信しません。
これにより、受講者をアクティブな状態に保ち、無料の追跡とターンバイターンのナビゲーションをその場で切り替えることができます。
概要 については、 API リファレンス に問い合わせて、どの受講者が追跡モードで作業しているかを確認してください。
ドライバーが道順をすでに知っているが、現在の道路名や旅程中の制限速度などの追加情報を取得したい場合は、トラッキングが便利です。
トラッキングを有効にする場合は 、次のフィーチャーSpeedBasedCameraBehavior
も有効にすることをお勧めします。
visualNavigator.cameraBehavior = SpeedBasedCameraBehavior()
このカメラモードは、現在の走行速度に基づいてマップ ビューを最適化するようにカメラの位置を自動的に調整します。
カメラのフォローを停止するには、次をコールしてください。
visualNavigator.setCameraBehavior(null)
これは、ジェスチャの処理を一時的に有効にする場合に、ガイダンス中にも役立ちます。 ターン・バイ・ターンナビ (矢印ナビ)が実行中の場合、ドライバーの注意をそらさないように自動的にトラッキングに戻すことをお勧めします。
旅程を準備します
HERE SDK は、マップ データ のルートプリフェッチをサポートしています。 これにより、ターン・バイ・ターンナビ (矢印ナビ) 中などのユーザー体験を改善して、一時的なネットワークの損失を適切に処理できます。
旅程が発生した地域にオフラインのマップがすでにダウンロードされている場合は、この操作は不要です。 この場合、すべてのマップ データ がすでに存在し、ネットワーク接続は必要ありません。 たとえば、専用の OfflineRoutingEngine
とは異なり 、Navigator
または VisualNavigator
は、キャッシュされたデータまたはオフライン マップ データにフォールバックする必要があるタイミングを自動的に決定します。 一般に、ナビゲーションにはマップ データ が必要です。マップ ビュー を表示せずにヘッドレスで実行された場合でも同様です。 この理由は、マップマッチングのためのナビゲーション中にマップ データ にアクセスし、たとえば制限速度などの特定の道路属性について通知する必要があるためです。 このデータは、デバイスで利用可能なデータから取得されます。または、利用できない場合は、ナビゲーション中にダウンロードする必要があります。 そのため、今後の道路を見越してより多くのデータをプリフェッチすることが有益です。 プリフェッチを使用しない場合、一時的な接続の損失はあまり適切に処理されません。
注
これはこのフィーチャーのベータリリースであるため、バグがいくつか発生したり、予期しない動作が発生する可能性があります。 関連する API は、非推奨プロセスなしで新しいリリースで変更されることがあります。
コンストラクタRoutePrefetcher
には、パラメータとしてインスタンスSDKNativeEngine
のみが必要です。 HERE SDK の初期化後、SDKNativeEngine.sharedInstance
経由で取得できます。
RoutePrefetcher
では、マップ データ を事前にダウンロードできます。 マップ データ が マップキャッシュにロードされます。 マップキャッシュには独自のサイズ制約があり、すでにデータが含まれている可能性があります。 RoutePrefetcher
は、新しいマップ データ を保存するために、古いキャッシュデータを削除する必要がある場合があります。
-
旅程を開始する前に、routePrefetcher.prefetchAroundLocation(currentGeoCoordinates)
を1 回コールすることをお勧めします。 このコールは、半径が 2 km の指定された場所をマップ データ が事前にマップキャッシュにプリフェッチし、ユーザーがルートのトラッキングを開始したときに十分なマップ データ が存在することを保証します。ただし、ルートがユーザーの現在の場所から開始されていることが前提です。
-
ナビゲーションが開始したら、次 routePrefetcher.prefetchAroundRouteOnIntervals(navigator)
を 1 回コールしてください。 現在指定されているインスタンスNavigator
に設定されているルートに沿って、経路内のマップ データ をプリフェッチします。 ルートが設定されていない場合、データはプリフェッチされません。 ルートコリドーのデフォルトの長さは 10 km 、幅は 5 km です マップ データ は、不連続の間隔でのみプリフェッチされます。 現在の経路の終点に達する 1 km 前にプリフェッチが開始されます。 プリフェッチは、 RouteProgress
イベントによって示される現在のマップマッチングした場所 に基づいて行われます。 最初のプリフェッチは、ルート沿いに 9 km の距離を走行した後に開始されます。 新しいルートがnavigator
に設定されている場合、このメソッドを再度呼び出す必要はありませんが、このメソッドが 2 回以上呼び出されても、悪影響はありません。
ナビゲーション 例のアプリ に、RoutePrefetcher
の使用例を示します。
RoutePrefetcher
がルートの開始時に正常に使用され、その後接続が失われた場合、キャッシュされたデータは、マップキャッシュが削除されるまで、今後のパワーサイクルであっても保持されます。 マップキャッシュの削除ポリシーの詳細について は、 ここ を参照してください。
- ナビゲーション を開始する前に、両方のメソッドを同時に呼び出すこともできます。 ただし、トレードオフのために、トリップ開始直後に必要なすべてのデータをプリフェッチするのに十分な時間がない場合があります。
prefetchAroundRouteOnIntervals()
ガイダンス中にネットワークトラフィックが継続的に増加することに注意してください。
もちろん、プリフェッチされたデータがない場合でもガイダンスを利用できますが、エクスペリエンスの最適化はあまり行われない場合があります。
どちらの呼び出しも、キャッシュされたマップ データ を利用する一時的なオフラインの使用例を最適化するのに役立ちます。 prefetchAroundLocation()
はナビゲーションユースケース の外部でも使用できますが 、prefetchAroundRouteOnIntervals()
には進行中のナビゲーションシナリオが必要です。
または 、ルート全体のマップ データを事前にプリフェッチすることもできます。 ルートのシェイプから作成されたGeoCorridor
のタイルデータRoutePrefetcher.prefetchGeoCorridor()
をプリフェッチするために使用します。 この処理には、ルートの長さ、経路の幅、およびネットワークに応じて、少し時間がかかることがあるため、PrefetchStatusListener.onProgress()
経由で進行状況が報告されます。 操作が完了すると、イベント PrefetchStatusListener.onComplete()
が送信されます。
注
ルートがすでにダウンロード Region
されたデータを通過する場合、経路のこれらの部分は再利用され、再度ダウンロードされることはありません。
マップ データをプリフェッチするもう 1 つの方法は、PolygonPrefetcher
で実装できます。 これにより、コンクリートから独立してデータを取得でき Route
ます。 代わりに、 データのダウンロード先を指定するには、GeoPolygon
のみが必要です。 このデータは、 RoutePrefetcher
の場合と同様に、一時的にマップキャッシュにのみ保存されます。 PolygonPrefetcher
では、 データをダウンロードする前に、予想されるダウンロード済みのMapDataSize
見積もりを行うこともできます。