道順を確認します
HERE SDK は 、 A から B までの最適な経路情報を計算するための本格的な機能のRoutingEngine
を提供します。これには、複数のウェイポイント と、各ターンのローカライズ可能な操作手順が含まれます。
目的のルート タイプ (最速または最短) とさまざまなルート オプション (速度プロファイル、ルート制限、ビネット オプションなど) を適切な設定を指定し、エネルギーを最も節約する最適なルートを見つけます。先進的なルーティング技術と専用の EV ルートプランニングサポートにより、 HERE は 地球をよりクリーンで安全にするお手伝い をします。
フィーチャーの概要 :
- ルートの計算: さまざまなトランスポートモードで複数のウェイポイントを使用してルートを計算します。
- Isolineルーティング: 時間、距離、または燃料消費量に基づいて、特定のポイントからの到達範囲を表す Isolineポリゴンを計算します。
- ルートに沿って検索: ルート全体に沿って場所を検索 します(このフィーチャーについては、「検索」セクションで説明します)。
- ルートのインポート / ルートマッチング: 他の API からルートをインポートできます。
- オフラインルーティング: インターネット接続が利用できない場合は、専用のオフラインルーティングエンジンに切り替えて、キャッシュ済みのマップ データまたは事前にロードされたオフラインマップデータのルートを計算できます。
ルートを取得
HERE SDK では、次のルートタイプがサポートされています。
- 乗用車でのルート案内
- タクシー乗り場への行き方。
- 徒歩ルート案内
- 自転車ルート案内
- カスタマイズ性の高いトラックオプションを備えたトラックルートの案内。
- スクーターのルート案内
- バスのルート案内
- 電気自動車が 最寄りの充電ステーションを見つけるためのルート案内(計算されたエネルギー消費量およびバッテリー仕様に基づく)。
- 高度にカスタマイズ可能な交通手段を備えた公共交通機関のルート案内(
TransitRoutingEngine
経由 )。
注
すべてのトランスポートモードは、RoutingEngine
でのオンラインルート計算に使用 できます。 一部のトランスポートモードは、キャッシュされたマップ データ でのオフラインルートの計算、またはOfflineRoutingEngine
とともにダウンロードされたオフラインマップにも使用できます。 サポートされているオフラインモードの概要について は、 ここを参照してください。
各ルートタイプは 、CarOptions
または TruckOptions
などの利用可能なルートオプションのいずれかによって決定されます。 ここ では、サポートされている各トランスポート モードで利用可能なすべてのルート オプションを見つけます。 これらのオプションは、ルートエンジン calculateRoute()
のメソッドで使用可能なオーバーロードに設定できます。
ルートエンジンを次のように作成して、旅程を開始します。
do {
try routingEngine = RoutingEngine()
} catch let engineInstantiationError {
fatalError("Failed to initialize routing engine. Cause: \(engineInstantiationError)")
}
新しい RoutingEngine
インスタンスを作成すると、上の図のように処理する必要があるエラーがスローされることがあります。 このようなエラーは、たとえば、 HERE SDK の初期化が事前に失敗した場合に発生することがあります。
次のステップとして、出発地と目的地 (どちらも GeoCoordinates
インスタンスを保持する Waypoint
タイプ) という 2 つのウェイポイントに基づいてルートを計算できます。以下では、車両に最適化されたルートを計算するために CarOptions
のデフォルトを設定します。
let carOptions = CarOptions()
routingEngine.calculateRoute(with: [Waypoint(coordinates: startGeoCoordinates!),
Waypoint(coordinates: destinationGeoCoordinates!)],
carOptions: carOptions) { (routingError, routes) in
if let error = routingError {
self.showDialog(title: "Error while calculating a route:", message: "\(error)")
return
}
let route = routes!.first
self.showRouteDetails(route: route!)
self.showRouteOnMap(route: route!)
self.logRouteViolations(route: route!)
}
複数の calculateRoute()
をコールすることができます。たとえば、異なるルーティングオプションを持つルートを並行して計算するために、このルートを呼び出すことができます。
注
ヒント : ドライバーが走行している場合、方位値はルート計算の改善に役立つことがあります。startingWaypoint?.headingInDegrees = location.bearingInDegrees
。
各ルート計算は非同期で実行されます。 完了すると、エラーの可能性があるリストRoute
またはRoutingError
が表示されます。 すべてうまく行けば、 nil になります。 エラーが発生した場合、ルートリストは nil です。 たとえば、指定したトランスポートモードでルートが実行できない場合、エンジンはルートを計算できません。
注
エラーがない場合 、ルートリストには 1 つの結果のみが含まれます。 ルートオプションを使用して代替ルートの数を指定することで 、追加 のルートバリアントを要求できます。 デフォルトでは、代替ルートなしでルートが計算されます。
上記のコード スニペットの showRouteDetails()
メソッドを使用して、操作指示を含むルートの詳細を表示します。 すべてのソースコードは、付属のサンプルアプリに記載されています。 操作手順については、以下で詳しく説明します。 showRouteOnMap()
メソッドには、マップ上でルートをレンダリングする方法の例が含まれています。 この点については、後述のセクションで簡単に説明します。
注 : 重要
ルートには 、ルートの計算後に発生する可能性のある問題を説明するNoticeCode
値のリストが含まれている場合があります。 たとえば、ルートがトンネルを回避する必要があり、可能な唯一のルートがトンネルを通過する必要がある場合、Route
には、要求されたトンネル回避の違反があったことを示す通知が含まれます。
- 違反の可能性がないか、常に計算済みの
Route
を確認することをお勧めします。 NoticeCode
はNotice
オブジェクトの一部です。 可能な Notice
オブジェクトのリストには、Route
の Section
ごとにアクセスでき ます。 - 違反が発生しなかった場合、リストは空になります。
- 違反の可能性 がある場合は、少なくとも 1 つの違反を含むルートをスキップすることをお勧めします。
ただし、要求されたルートオプションおよび実際の NoticeCode
値のリストによって、実装はケースバイケースに判断します。 ルートオプションの詳細については、次のセクションを参照してください。 重要 : わかりやすいよう に、このガイドのコードスニペットでは、通知の 列挙型 (enum) 値を評価しません。
次の方法で、可能性のあるルート通知を検出できます。
private func logRouteViolations(route: Route) {
let sections = route.sections
for section in sections {
for notice in section.sectionNotices {
print("This route contains the following warning: \(notice.code)")
}
}
}
注
ヒント : すべてのルートにルート沿いの標高値が含まれています。 たとえば、予定されている自転車旅程の高度プロファイルを作成します。
各トランスポートモードにルートオプションを使用
上の例では、自動車ルートを計算する新しいCarOptions
インスタンスを設定しました。 各トランスポートモードに専用のルートオプションを使用すると、他のトランスポートモードのルートを計算できます。 次のルートオプションがあります。
-
CarOptions
車両ルートを計算するには、 route.getRequestedTransportMode()
は、TransportMode.CAR
を返します。 -
TruckOptions
トラックルートを計算するには : route.getRequestedTransportMode()
は、TransportMode.TRUCK
を返します。 -
PedestrianOptions
歩行者のルートを計算するには: route.getRequestedTransportMode()
は、 TransportMode.PEDESTRIAN
を返します 。 -
EVCarOptions
と EVTruckOptions
電気自動車のルートを計算するには、 route.getRequestedTransportMode()
は、 TransportMode.CAR
またはTransportMode.TRUCK
を返します 。 -
ScooterOptions
スクーターのルートを計算するには: route.getRequestedTransportMode()
を返します TransportMode.SCOOTER
。 -
BicycleOptions
自転車のルートを計算するには: route.getRequestedTransportMode()
は、TransportMode.BICYCLE
を返します。 -
TaxiOptions
タクシーのルートを計算するには : route.getRequestedTransportMode()
は、TransportMode.TAXI
を返します 。 -
BusOptions
バスのルートを計算するには : route.getRequestedTransportMode()
は、TransportMode.BUS
を返します。 -
TransitRouteOptions
公共交通機関のルートを計算 するには ( TransitRoutingEngine
経由でのみ利用可能 ) route.getRequestedTransportMode()
は、TransportMode.PUBLIC_TRANSIT
を返します 。
TransportMode
は、ルート計算が完了した後にルーティング エンジンによって設定されます。getRequestedTransportMode()
はルート オプションからトランスポート モードを決定しますが、Route
の各 Section
は異なるトランスポート モードを持つことができます。route.getSectionTransportMode()
は、ルート計算に使用する必要がある実際の SectionTransportMode
を提供します。 特定のセクション - 上記のトランスポート モードに加えて、FERRY
や CAR_SHUTTLE_TRAIN
などのトランスポート モードもリストされています。
デフォルトでは、始点と終点のウェイポイントのみを通過する場合、導かれたルートには 1 つのルートSection
のみが含まれます。 各 route
オブジェクトには、設定されているウェイポイントモードおよびトランスポートモードの数に応じて、より多くのルートセクションを含めることができます。 セクションは、ルートを複数の論理パーツに分割するルートレッグとして機能します。 ここで詳細情報を参照できます。
ルートを計算する前に、メイントランスポートモードがユーザーによって指定されますが、最終的なトランスポートモードは、Section
ごとにルーティングエンジンによって設定されます。
注
Route
には複数のSectionTransportMode
を含めることができます。 このような場合、ルートは Section
別のルートに分割され、トランスポートモードの変更が示されます。 基本的に、トランスポートモードを変更するには 、たとえばフェリーに乗るために車を出るときに、旅程の停止が必要です。 ただし、マルチモーダルルーティング (または インターモーダルルーティング)はサポートされていません。 目的地として公園内の観光スポットが含まれている場合、最後のウェイポイントは、車で到達可能な公園の前が最後の場所としてマップマッチングされ、ルートには歩行者セクションは含まれません。
このようなギャップは 、RoutePlace
オブジェクトのoriginalCoordinates
とmapMatchedCoordinates
を比較することで検出できます。 フォールバックとして、適切なトランスポートモードを使用して、これら 2 つの座標間の距離を新しいルート計算で埋めることをアプリケーションで決定できます。このようなモーダルルートは、を利用する代わりにタクシーまたは公共交通機関を利用することをユーザーが好む場合があるため、さまざまなオプションで構成できます 徒歩。 HERE SDK は、このようなモーダルルートを個別の要求としてのみサポートするため、アプリケーションはフォールバックロジックを実装する必要があります。
ルートに沿ったすべての地理座標がマップマッチングされることに注意してください (スナップイン道路とも呼ばれます)。 Waypoints
を追加した場合は、マップマッチングも行われ、元の座標は、Section
の始点と終点を示す RoutePlace
内のマップマッチング座標と比較できます。
利用可能なすべてのルートオプションを使用して、必要に応じてルート計算を最適化するための複数のパラメータをさらに指定できます。
上記の各オプションには、共通のオブジェクト RouteOptions
を保持するフィールドが含まれています。 このオプションを使用すると、代替ルートの数などの一般的なオプションを指定できます。また、OptimizationMode
で移動時間とルートの長さに基づいて最適なルートを検索することもできます。
注
デフォルトでは、ルートは ルートモードfastest
を使用して計算されます。
または、アルゴリズムを変更することもできます。 たとえば、目的地にすばやく到達したい場合に、ルートの長さが自分にとってそれほど重要ではない場合は、RouteOptions
を経由するfastest
のルートモードを選択します。 ルートを短くして、時間がそれほど重要でない場合にshortest
を選択します。
最適なルートを見つけるために、ルーティングアルゴリズムでは多数の異なるパラメータが考慮されます。 これは、アルゴリズムが常に 最短 ルートまたは最速ルートを提供することを意味するものではありません。 たとえば、次の道路ネットワークについて考えてみます。
図 : どのルートを選択しますか? A から B への旅程を計画する場合 、 4 つの異なる道路から選択できます。 緑のルートが高速道路を表しているとし ます。このルートは最速のルートですが、都市を案内する他のルートよりも長くなっています。
代わりに最短 ルートを使用する場合は、黄色と赤色のルートが短くなりますが、ルートアルゴリズムによって青色のルートが優先されることがあります。 その理由をお聞かせください。 黄色の道路は最短ルートですが、フェリーが発着する川を渡る必要があります。 このアルゴリズムでは、時間のかかるものと見なすことができます。 そのため、赤色または青色のルートを黄色のルートよりも優先することができますが、どちらも若干長くなります。
他の 2 つのオプションを確認してみましょう。 青と赤のルートを比較する場合、ルーティングアルゴリズムは青のルートを最短ルートとして推奨することがありますが、赤のルートよりもわずかに長くなります。通常、複数のターンは運転者にとって有益ではありません。 この場合、赤色のルートには青色のルートよりも多くのルートが含まれていますが、青色のルートはわずかに長いため、推奨ルートとなる場合があります。 ルート探索アルゴリズムは、ターンおよび交通信号やドライバーの減速を引き起こす可能性のある鉄道の踏切など、他の多くの道路特性を負の要因とします。
注
HERE SDK では、一般的なルーティングオプションに加えて、トラックルーティングなど、サポートされているさまざまなトランスポートモードに特化したオプションを提供しています。このオプションでは、次のように指定できます。 トラックの寸法。道路幅やトンネルの高さなど、トラックが適したルートのみを検索できます。
導かれたルートは特定の条件に基づいて最適化されますが、信頼したくない状況が生じることがあります。 ベルリン市内を巡る旅を想像してみてください。ベルリンの観光名所を巡りたい場合は、最短ルートまたは最短ルートを見つけることはできません。 このような場合は、追加のウェイポイントを設定することをお勧めします。 以下の例を参照してください。
トラックルートを取得
HERE SDK は、ルート計算のためにさまざまなトランスポートモード(上記を参照)をサポートしています。 車両に最適化されたルートの計算方法を示す上記の例と同様に、トラックなどの他の輸送タイプのルートを計算することもできます。
既定のオプションを設定することで、トラック用に最適化されたルートをすでに取得できますが、トラックに最適なルートを検索するためのオプションが数多く用意されています。
たとえば、TruckOptions
には、トラックの寸法を指定する TruckSpecifications
などの追加のフィールドが含まれています。これらのフィールドは、オプションで車両重量およびその他のパラメータを考慮に入れるように適用できます。
トラックの取り回しの詳細については、「トラックガイダンス」セクションを参照してください。
公共交通機関のルートを取得
TransitRoutingEngine
を使用して、 A から B への公共交通機関のルートを計算します。その間には複数のウェイポイントがあります。 GitHub で PublicTransit のサンプルアプリを探し て、その方法を確認できます。
追加のウェイポイントを使用してルートを形成
デフォルトでは、始点と終点のウェイポイントのみを通過する場合、導かれたルートには 1 つのルートSection
のみが含まれます。 各ルートオブジェクトには、設定されているウェイポイントの数に応じて、より多くのルートセクションを含めることができます。 セクションは 、 ルートを複数の論理パーツに分割するルートレッグとして機能します。
ウェイポイントは、より多くのセクションまたはルートの形状を決定するためにユーザーが設定できる座標です ( フェリーで川を横断する場合などに便利です ) 。
オンライン RoutingEngine
でサポートされているウェイポイントの数は、最大で約 200 個に制限されています。
ウェイポイントには、次の 2 つのタイプがあります。
-
stopover
: デフォルトのウェイポイントタイプ。 このポイントを通過することが保証されているため、操作指示のリストに表示され、ルートが別々のルートセクションに分割されます。 -
passThrough
: 操作指示リストに表示されない場合があり、タッチ入力の結果など、ルートを形成するヒントとして扱われます。 このタイプ では、ルートは別々のセクションに分割されません。
新しい Waypoint
オブジェクトを作成する場合、stopover
タイプはデフォルトで設定されます。このタイプは、最初と最後のウェイポイントで使用されるタイプである必要があります。 2 つのウェイポイントのみが始点および終点として機能する場合、ルートは次のようになります。
図 : 出発地点と目的地の間に 1 つのルートセクションがあります。 RoutingEngine
は、複数のウェイポイントを処理できます。 基盤となるアルゴリズムは、提供された配列の順序およびWaypointType
の順序を遵守しながら、すべてのウェイポイントを接続する最適なパスを探そうとします。 各 stopover
のウェイポイントが、出発地と目的地の間で渡されます。目的地は、それぞれウェイポイントリストの最初の項目と最後の項目です。
let waypoint1GeoCoordinates = createRandomGeoCoordinatesInViewport()
let waypoint2GeoCoordinates = createRandomGeoCoordinatesInViewport()
let waypoints = [Waypoint(coordinates: startGeoCoordinates),
Waypoint(coordinates: waypoint1GeoCoordinates),
Waypoint(coordinates: waypoint2GeoCoordinates),
Waypoint(coordinates: destinationGeoCoordinates)]
let carOptions = CarOptions()
routingEngine.calculateRoute(with: waypoints,
carOptions: carOptions) { (routingError, routes) in
if let error = routingError {
self.showDialog(title: "Error while calculating a route:", message: "\(error)")
return
}
let route = routes!.first
self.showRouteDetails(route: route!)
self.showRouteOnMap(route: route!)
self.logRouteViolations(route: route!)
}
上の図に示すように、コード スニペットを使用してルートに 2 つの stopover
ルートウェイポイントを追加することで、出発地と目的地の間に 3 つのルートセクションが作成されました。
注
ウェイポイントリストの順序は、ルートに沿って渡される順序を定義します。
図 : 2 つのウェイポイントを追加しています。 目的地までの移動にかかる推定時間やルートの全長(メートル単位)など、ルートに関する追加情報は、以下のように Route
オブジェクトから取得できます。
let estimatedTravelTimeInSeconds = route.duration
let lengthInMeters = route.lengthInMeters
移動時間と移動距離は、それぞれの Section
で利用でき ます。 追加の stopover
経由地がない場合、ルートには 1 つのルートだけが含まれます Section
。 追加の stopover
経由地が指定されている場合、ルートは各経由地間、出発地から最初のウェイポイントまで、最後のウェイポイントから目的地までのルートを複数のルート区間に分けて表示します。
注
デフォルトでは、追加のウェイポイントによってルートが個別のセクションに分割され、ルートがこのポイントを通過し、そのポイントに対する操作指示が生成されます。
各 Section
は、ルートのシェイプが GeoPolyline
で表されています。この配列では、最初の座標が出発点を示し、最後の座標が目的地を示します。
これは、たとえば、マップポリラインを Section
ごと異なる色で使用して、マップ上のルートを表示する場合に役立ち ます。 ただし、ポリラインを Route
オブジェクトから直接取得することもできます。 MapPolyline
以下のコード スニペットは、各経由地の間に描画されたを使用して、開始ポイントと宛先を含めて、この機能を実装する方法を示しています。
let routeGeoPolyline = route.geometry
let routeMapPolyline = MapPolyline(geometry: routeGeoPolyline,
widthInPixels: 20,
color: UIColor(red: 0,
green: 0.56,
blue: 0.54,
alpha: 0.63))
mapView.mapScene.addMapPolyline(routeMapPolyline)
以下の最初のスクリーンショットは、追加のウェイポイントがないルートを示しています。そのため、ルートセクションは 1 つだけです。 出発地と目的地は、緑で囲まれた地図のマーカーで示されます。 円で囲まれたオブジェクトを描画するコードは ここにはありませんが、必要に応じてサンプルのソースコードから参照できます。
スクリーンショット: マップにルートを表示。 2 つ目のスクリーンショットには、上記と同じルートが表示されますが、 2 つのstopover
のウェイポイントが追加され、赤い丸で囲まれたマップマーカーで示されます。 このため、ルートには 3 つのルートセクションが含まれています。
スクリーンショット: 2 つのウェイポイントが追加されたルートを表示。 ルートを拡大表示
一部の使用例では、計算されたルートをズームすると便利です。 Camera クラスを使用すると、ルートが収まるようにビューポイントを簡単に調整できます。
let routeGeoBox = route?.boundingBox
camera.lookAt(area: routeGeoBox!,
orientation: GeoOrientationUpdate(bearing: nil, tilt: nil))
ここでルートオブジェクトの外側のバウンディング ボックスを使用します。 これを使用すると、カメラを即座に更新できます。 ズーム レベルとカメラのターゲットポイントが変更され、指定された境界矩形がビューポイントに正確に収まるようになります。 さらに、方向を指定して、より多くのカメラパラメーターを指定できます。 ここではデフォルトの値を使用します。 lookAt()
の呼び出しによってビューが即座に変更されます。
ほとんどの使用例では、アニメーションを使用してルートを拡大縮小する方がユーザーの操作性が向上します。 次の例では、GeoBox
に 50ピクセルのパディングを加えてズームしています。
func animateToRoute(route: Route) {
let bearing: Double = 0
let tilt: Double = 0
let origin:Point2D = Point2D(x: 50.0, y: 50.0)
let sizeInPixels:Size2D = Size2D(width: mapView.viewportSize.width - 100, height: mapView.viewportSize.height - 100)
let mapViewport:Rectangle2D = Rectangle2D(origin: origin, size: sizeInPixels)
let update:MapCameraUpdate = MapCameraUpdateFactory.lookAt(area: route.boundingBox, orientation: GeoOrientationUpdate(GeoOrientation(bearing: bearing, tilt: tilt)), viewRectangle: mapViewport)
let animation: MapCameraAnimation = MapCameraAnimationFactory.createAnimation(from: update, duration: TimeInterval(3), easingFunction: EasingFunction.inCubic)
mapView.camera.startAnimation(animation)
}
アプリの例CameraKeyframeTracks
では、この方法を示しています。
操作手順を取得
各 Section
には、目的地に到着するためにユーザーが従う必要がある操作手順が含まれています。 1 つの Maneuver
オブジェクトには、曲がるたびに操作と操作が必要な場所が含まれています。 このアクションは、「出発」や「左折」などの道順を示す場合があります。
let sections = route.sections
for section in sections {
logManeuverInstructions(section: section)
}
ここには、セクションごとの操作指示にアクセスするためのコードがあります。
private func logManeuverInstructions(section: Section) {
print("Log maneuver instructions per route section:")
let maneuverInstructions = section.maneuvers
for maneuverInstruction in maneuverInstructions {
let maneuverAction = maneuverInstruction.action
let maneuverLocation = maneuverInstruction.coordinates
let maneuverInfo = "\(maneuverInstruction.text)"
+ ", Action: \(maneuverAction)"
+ ", Location: \(maneuverLocation)"
print(maneuverInfo)
}
}
これは、経路全体を記述する操作指示リストを書面で簡単に作成する場合に役立ちます。 たとえば 、 列挙型 (enum)の ManeuverAction
を使用して独自のルーティングエクスペリエンスを構築できます。
スクリーンショット: 操作手順を含むルートプレビューを示す画面の例。 注
Navigator
または VisualNavigator
から取得した場合、ナビゲーション中に Maneuver
説明テキスト(maneuverInstruction.text
)は空になります。 Route
インスタンスから取得した場合にのみ、ローカライズされた命令が含まれます。 ManeuverAction
列挙型(enum)はナビゲーション中に視覚的なインジケータを表示するために使用され、テキストによる指示は、旅程を開始する前に操縦をプレビューするために、より多くのリストに入ることになっています。
反対に、maneuverInstruction.roadTexts
、maneuverInstruction.nextRoadTexts
および maneuverInstruction.exitSignTexts
は、ナビゲーション中のターンバイターン操作の一部として表示されることを意味します。したがって、これらの操作は、Maneuver
が Navigator
または VisualNavigator
から取得された場合にのみ空ではありません。 Route
インスタンスから取得した場合、これらの属性は常に空になります。
API リファレンス では、利用可能な 操作の概要を確認できます。
次の表は、プレビューの説明とアセットの例を含むすべてのアイテムManeuverAction
を示しています。 HERE SDK自体には、操作アイコンは付属していません。 アセットは、オープンソース のHERE Icon Libraryの一部として、さまざまな密度のSVGまたはソリッドPNGとして利用できます。
使用可能な操作アクションは 、APIリファレンスに表示される順序でソートされます。
操作アクション | 説明の例 | アイコンの例 |
出発 | 「出発 <road name>」などの出発操作。 | |
到着 | 「到着」などの到着操作。 中間ウェイポイントの説明例: 」に到着 <road name | waypoint>。 ルートの目的地の場合: 」に到着 <road name | destination name | destination>。 | |
左転回をする | 「左転回を行う <next road name>」などの左転回操作。 | |
鋭角に左に曲がる | 「鋭角に左に曲がる <next road name>」などの鋭角な左折操作。 | |
左折する | 「左折」などの左折操作 <next road name>。 | |
少し左に曲がる | 「左折してください <next road name>」など、少し左に曲がる操作。 | |
継続オン | 「続行」などの操作を続行 <road name>します。 | |
少し右に曲がる | 「右折してください <next road name>」など、少し右に曲がる操作。 | |
右折する | 「右折」などの右折操作 <next road name>。 | |
鋭角に右に曲がる | 「鋭角に右に曲がる <next road name>」などの鋭角な右折操作。 | |
右転回する | 右転回操作(「右転回する <next road name>」)。 | |
左側の出口を出る | 「左側の出口から出て <next road name>」(左側の出口で出る)などの左出口の操作。 | |
右側の出口を出る | 「右側の出口から出て <next road name>」(右側の出口で出る)などの右出口の操作。 | |
左ランプを出る | 「左ランプを出る」などの左ランプ出口操作。 | |
右ランプを出る | 「右ランプを出る」などの右ランプ出口操作。 | |
左車線を進む操作 | 左車線を進む操作(「左車線を進んで <next road name>」など)。 | |
中央の車線を進む | 「中央の車線を進む <next road name>」などの中央車線の進行操作。 | |
右の車線を進む | 右車線を進む操作(「右車線を進んで <next road name>」など)。 | |
左側から高速道路に合流する | 「左側から高速道路に合流する」など、左側からの操作で高速道路に合流します。 | |
右側から高速道路に合流する | 「右側から高速道路に合流する」など、右側からの操作で高速道路に入ります。 | |
左ロータリー(環状交差点)に入る | 「左ロータリー(環状交差点)に入る」など、右ロータリーを操作します ( 左側通行 ) 。 | |
右ロータリー(環状交差点)に入る | 「右ロータリー(環状交差点)に入る」など、右ロータリーを操作します ( 右側通行 ) 。 | |
左ロータリー(環状交差点)を通過する | 「左ロータリー(環状交差点)を通過する」など、ロータリーを操作します ( 左側通行 ) 。 | |
右ロータリー(環状交差点)を通過する | 「右ロータリー(環状交差点)を通過する」など、ロータリーを操作します ( 右の交通量 ) 。 | |
左ロータリー(環状交差点)の最初の出口を出る | 「左ロータリー(環状交差点)の最初の出口を出る」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)の2番目の出口を出る | 「左ロータリー(環状交差点)の2番目の出口を出る」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)の3番目の出口を出る | 「左ロータリー(環状交差点)の3番目の出口を出る」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)の4番目の出口を出る | 「左ロータリー(環状交差点)の4番目の出口を出る」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)の5番目の出口を出る | 「左ロータリー(環状交差点)の5番目の出口を出る」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)の6番目の出口を出る | 「左ロータリー(環状交差点)の6番目の出口を出る」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)の7番目の出口を出る | 「左ロータリー(環状交差点)の7番目の出口を出る」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)8番目の出口を出る | 「左ロータリー(環状交差点)8番目の出口を出る」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)の9番目の出口を出る | 「左ロータリー(環状交差点)の9番目の出口を出てる」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)の10番目の出口を出る | 「左ロータリー(環状交差点)の10番目の出口を出る」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)の11番目の 出口を出る | 「左ロータリー(環状交差点)の11番目の
出口を出る」などのロータリー操作(左側通行)。 | |
左ロータリー(環状交差点)の12番目の出口を出る
| 「左ロータリー(環状交差点)の12番目の出口を出る」などのロータリー操作(左側通行)。 | |
右ロータリー(環状交差点)の最初の出口を出る | 「右ロータリー(環状交差点)の最初の出口を出る」などのロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)の2番目の出口を出る | 「右ロータリー(環状交差点)の2番目の出口を出る」などのロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)の3番目の出口を出る | 「右ロータリー(環状交差点)の3番目の出口を出る」などのロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)の4番目の出口を出る | 「右ロータリー(環状交差点)の4番目の出口を出る」などのロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)の5番目の出口を出る
| 「右ロータリー(環状交差点)の5番目の出口を出る」などのロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)の6番目の出口を出る | 「右ロータリー(環状交差点)の6番目の出口を出る」などのロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)の7番目の出口を出る | 「右ロータリー(環状交差点)の7番目の出口を出る」などのロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)8番目の出口を出る | 「右ロータリー(環状交差点)8番目の出口を出る」などのロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)9番目の出口を出る | 「右ロータリー(環状交差点)9番目の出口を出る」などの右ロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)の10番出口を出る | 「右ロータリー(環状交差点)の10番出口を出る」などのロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)の11番出口を出る | 「右ロータリー(環状交差点)の11番出口を出る」などのロータリー操作(右側通行)。 | |
右ロータリー(環状交差点)の12番目の出口を出る | 「右ロータリー(環状交差点)の12番目の出口を出る」などのロータリー操作(右側通行)。 | |
現時点では、leftRoundaboutPass
および rightRoundaboutPass
のHEREアセットは SVGとしてのみ使用でき、一部の操作アセットはサブフォルダ"wego-fallback-roundabout"でのみ使用できます。 PNG表現の場合、 MSDKUI オープンソースプロジェクトもフォールバックとして使用できます。
ルート沿いの交通状況の検索
渋滞に巻き込まれた場合の総時間を取得するには、次のいずれかの操作を行います。
let estimatedTrafficDelayInSeconds = route.trafficDelay
ルートの個々のセクションでは、交通状況に関するより詳細な情報を利用できます。 操作に加えて(上記を参照)、各Section
Route
には、ルートが計算された時点のトラフィックフローの状況に関する情報が含まれています。
各インスタンス Section
には、さまざまな量 のインスタンスTrafficSpeed
を含めることができます。 これらの値は 、Span
に沿って次のSpan
までの間有効です。 各 Span
ジオメトリは、ルート全体のポリライン 形状の一部であるポリラインによって表されます。
次のコード スニペットは Section
の最初の Span
の TrafficSpeed
要素を取得する方法を示しています。
let firstSection = route.sections.first
let firstTrafficSpeed = firstSection?.spans.first?.trafficSpeed
TrafficSpeed
にはbaseSpeedInMetersPerSecond
が含まれています。これは、予想されるデフォルトの走行速度です。 これは、道路の現在の制限速度とは異なる場合があります。道路状況が悪いと、走行速度が遅くなる可能性があります。 さらに、 trafficSpeedInMetersPerSecond
での現在の交通状況に基づいて、推定実際の走行速度を取得できます
トラフィックフローレイヤで使用されるカラーエンコーディングと同様 に、 0 (トラフィックなし) ~ 10 (道路がブロックされている)の範囲のjamFactor
を使用して、ルートに沿ったトラフィックを指定できます。 HERE SDK のトラフィックフィーチャーの詳細については、「トラフィック」セクションを参照してください。
この値を適切な色にマップする方法の例を次に示します。
図 : 交通渋滞の要因。 通常、 jamFactor
は次のように解釈されます。
- 0 <=<4
jamFactor
: 渋滞なし、または少しの渋滞。 - 4 <=
jamFactor
<8 : 中程度または低速のトラフィック。 - 8 <=<10
jamFactor
: 渋滞しています。 -
jamFactor
= 10 : 通行できない、例:道路が閉鎖されている。
jamFactor
TrafficSpeed
表示値 は 、道路タイプおよびその他のパラメータを考慮せずに、 trafficSpeedInMetersPerSecond
/baseSpeedInMetersPerSecond
- の比率から線形に計算されます。 したがって、提供さ jamFactor
れたは、マップ ビュー のトラフィックフローの表示と正確に一致するとは限りません(有効な場合)。
スクリーンショット: 渋滞係数を使用してルート上のトラフィックを視覚化。 ルートに沿ったトラフィックを表示する場合は 、セクションの各スパンに複数の色付きのMapPolyline
オブジェクトをレンダリングすることを検討してください。
private func showTrafficOnRoute(_ route: Route) {
if route.lengthInMeters / 1000 > 1000 {
print("Skip showing traffic-on-route for longer routes.");
return
}
for section in route.sections {
for span in section.spans {
let trafficSpeed = span.trafficSpeed
guard let lineColor = getTrafficColor(trafficSpeed.jamFactor) else {
continue
}
guard let spanGeoPolyline = try? GeoPolyline(vertices: span.polyline) else {
print("Error: Initialization of GeoPolyline failed.")
return
}
let trafficSpanMapPolyline = MapPolyline(geometry: spanGeoPolyline,
widthInPixels: 10,
color: lineColor)
mapView.mapScene.addMapPolyline(trafficSpanMapPolyline)
mapPolylineList.append(trafficSpanMapPolyline)
}
}
}
private func getTrafficColor(_ jamFactor: Double?) -> UIColor? {
guard let jamFactor = jamFactor else {
return nil
}
if jamFactor < 4 {
return nil
} else if jamFactor >= 4 && jamFactor < 8 {
return UIColor(red: 1, green: 1, blue: 0, alpha: 0.63)
} else if jamFactor >= 8 && jamFactor < 10 {
return UIColor(red: 1, green: 0, blue: 0, alpha: 0.63)
}
return UIColor(red: 0, green: 0, blue: 0, alpha: 0.63)
}
パフォーマンス上の理由から、長いルートのトラフィックレンダリングはスキップします。この例では、トラフィックを持つ各スパンが個別の折れ線としてレンダリングされるためです。
-
さらに、 TrafficEngine
を使用して、ルートに沿った交通障害を照会できます。 このためには、Route
の座標から GeoCorridor
を作成する必要があります。 また、halfWidthInMeters
を設定して、コリドーの半径も指定してください 。 GeoCorridor
の長さと幅には制限があります。 Traffic Example アプリ を確認して、TrafficEngine
の使用方法を確認してください。 このガイドの 交通状況を確認のセクションも確認してください。
-
ルート上の基本的な交通障害情報にのみ関心がある場合は、Section.getTrafficIncidents()
を呼び出して、Route
インスタンスから Section
ごとに交通状況の概要を直接取得できます。 結果 TrafficIncidentOnRoute
のオブジェクトには、TrafficEngine
で使用できるデータの小さなサブセットが含ま れていますが、概要を最初に示すと便利です。
ルート上のトラフィックをレンダリングするだけでなく、 TrafficIncidentType
に基づいてトラフィックインシデントをアイコンとして表示することもできます。 次のカテゴリは、オブジェクトRoute
の一部として重複しています。
-
accident
: 交通事故。 -
congestion
: 交通渋滞。 -
construction
: 建設工事。 -
disabledVehicle
: 道路上の車両の転覆または故障。 -
laneRestriction
: 車線規制。 -
massTransit
: 鉄道や地下鉄などの大量輸送機関を含む事故。 -
plannedEvent
: スポーツイベントやフェスティバルなどの活動に関する事故。 -
roadClosure
: 道路閉鎖。 -
roadHazard
: 倒木や信号が消えたりするなど、道路上の危険な障害。 -
weather
: 悪天候。 -
other
: 他のどのカテゴリーにも当てはまらない既知の事故。 -
unknown
: 特定の障害に分類されない事象。
HERE SDKではこのようなアイコンアセットは公開されませんが 、マップフィーチャレイヤtrafficIncidents
を有効にして、すべてのインシデントをマップ上にアイコン付きで表示できます。 同様に 、trafficFlow
レイヤを有効にして、道路上の一般的なトラフィックフローを表示することもできます。 詳細 については、交通状況を確認セクションをご覧ください。
注
refreshRoute()
経由でルートを更新すると、ルートの交通情報を更新できます。 以下のセクションを参照してください。 または、ガイダンスの最中にDynamicRoutingEngine
を使用することも検討してください。
今後の制限速度などの確認
このオブジェクトRoute
は、Route
に沿って詳細な情報を公開 し、今後の制限速度、道路の属性と道路名、動的な交通情報などを把握します。
次の属性を確認してください: Span.sectionPolylineOffset
、Span.dynamicSpeedInfo
、Span.streetAttributes
、Span.carAttributes
、Span.truckAttributes
、Span.scooterAttributes
、Span.walkAttributes
、Span.durationInSeconds
、Span.streetNames
、Span.routeNumbers
、Span.speedLimitInMetersPerSecond
、Span.consumptionInKilowattHours
、Span.functionalRoadClass
、Span.duration
、Span.baseDuration
。 属性の完全なリストについては、 API リファレンス を参照してください。
各属性はスパンごとに指定され、スパンの全長にわたって有効です。 また、 2 つの交差点の間にある道路ネットワーク の一部を示すセグメント ID も検索されることがあります。 Span
は 、ルート関連の概念です。ルートの一部で、同じ属性を持ちます。 同じセグメントに複数のスパンを含める ことができ、通常、各セグメントには開始オフセット と終了オフセット があります。
Span
は、ルートセグメントの最小の部分を定義し、その曲率がのリストGeoCoordinates
として公開されます。
ルート沿いのトールコストを取得
ルートの個々のセクションに沿って、通行料金を計算できます。
注
これはこのフィーチャーのベータ版です。このため、いくつかのバグや予期しない動作が発生する可能性があります。 関連する API は、非推奨プロセスなしで新しいリリースで変更されることがあります。
通行料金を取得するには、フラグRouteOptions.enableTolls
を設定する必要があります。 デフォルトでは、false
に設定されています。 このフラグを有効にすると 、API リファレンス で定義されているように、通行料金の該当するトランスポートモードの通行料金データが要求されます。
トールコストは、Section.tolls
を使いPaymentMethod
、TollFare
およびToll
の情報を取得します。
ナビゲーション中 - ルートをフォロー中 - RoadAttributesDelegate
現在 isTollway
の道路でトールの支払いが必要かどうかを知らせるなど、新しい道路属性を知らせるを使用できます。
道路のフィーチャーで回避
トンネル、高速道路、低排出ガス地帯(LEZ)、地域、フェリー、料金、その他の道路の特徴(急カーブなど)を除外するためにAvoidanceOptions
を使用します。 RoadFeatures
, ZoneCategory
, GeoBox
, CountryCode
エレメントなどのリストを渡すことができます
RoadFeatures
には、 トンネルや有料道路などの道路固有のフィーチャーが含まれています。 たとえば、すべての高速道路を走行から除外するには、フィーチャーリストに controlledAccessHighway
を追加します。
AvoidanceOptions
は、ローカリゼーションや単位オプションなど、他のルートオプションと組み合わせて、目的のトランスポートモードのオプションに設定できます。 たとえば、車では、 CarOptions
、トラックでは TruckOptions
を使用するなどです。 これらのオプションは、ルートの計算時に読み取られ、AvoidanceOptions
の場合 、エンジンは一覧表示されているフィーチャーを回避しようとします。
スクリーンショット: 回避エリアのない2つのルートと回避エリアのある2つのルート。 ルートを更新
Route
オブジェクトに含まれているトラフィックフロー情報は、ルートが計算された時間帯に有効です。上記を参照してください。 この情報を後で更新する場合は、ルートを更新できます。
ルートのルートオプションを更新することもできます。
let refreshRouteOptions = RefreshRouteOptions(taxiOptions)
routingEngine.refreshRoute(routeHandle: route.routeHandle!,
startingPoint: Waypoint(coordinates: GeoCoordinates(latitude: 13.45, longitude: 53.56)),
refreshRouteOptions: refreshRouteOptions) { (routingError, routes) in
if (routingError == nil) {
let newRoute = routes?.first
} else {
}
}
このためには、ルートが計算される前にRouteOptions.enableRouteHandle
経由で要求されるRouteHandle
を把握しておく必要があります。
また、ルートの更新は、ルートオプションをあるトランスポートタイプから別のトランスポートタイプに変換したり、特定のオプションを更新したりする場合に役立ちます。 たとえば、徒歩ルートがトラックルートに変換されたなど、変換ができない場合、 routingError
が発生します。
新しい出発地点を指定して、ルートを短縮することもできます。 新しいルートは計算されないため、新しい出発地点は元のルートに非常に近い位置にある必要があります。 新しい出発地点が遠すぎると、routingError
が発生します。
進行中のターン・バイ・ターンナビ (矢印ナビ)中にドライバーがルートから逸脱した場合、迂回路の計算を新たに行う必要があるため、ルートを更新するだけでは不十分です。 このような場合 returnToRoute()
は、新しい出発地点を設定してルート全体を再計算するか、または元の代替ルートを保持できる方法を使用すると便利です。
ターン・バイ・ターンナビ (矢印ナビ) 中 にルートを更新して、最新の交通渋滞遅れアップデートを先に取得できます。 更新されたルートをNavigator
に設定する前に、ルートの最後の場所を新しい出発地点として設定する必要があります。 ただし、更新処理中にドライバーがすでに進行している場合、予期しない結果が生じる可能性があります。 いずれの場合も、 ETA を更新するだけで、新しい出発地点が既存のルートにある 場合、必ずしも新しいルートを設定する必要はありません。 代わりに、交通遅延時間を含む更新済みの ETA を使用できます。前方ルートの REST は 変更されません。 ガイダンス中に新しいルートを設定すると、新しいナビゲーションセッションが効果的に開始されます。
代わりに、最後の場所 と 現在のセクションインデックスを設定する必要がある DynamicRoutingEngine
を使用することを検討してください。 この情報は、次 dynamicRoutingEngineOptions.pollInterval
の到達時に使用されます。 トレードオフとして、これは即時の更新にはつながりません。また、現在の交通障害物を迂回するより適切なルートが見つかった場合、ルートの形状が変更される可能性があります。 ここでも、 refreshRoute()
と同様に、新しいルートを設定するかどうかを決定する必要があります。
注
ルートの更新は OfflineRoutingEngine
ではサポートされていません - 現在の交通状況をクエリするにはオンライン接続が必要です。同様 に、DynamicRoutingEngine
にもオンライン接続が必要です。
ルートに戻る
RoutingEngine
は、現在の交通状況に基づいて既存のルート(上記を参照)を更新できます。 結果として、前のルートよりも高速な新しいルートが作成されることがあります。 ただし、新しい startingPoint
は元のルートに非常に近いものにする必要があります。
startingPoint
がルートから離れている場合に対処する必要がある場合は、RoutingEngine
のreturnToRoute()
機能を使用することを検討してください。 たとえば、ローカルの交通状況により、ドライバーが迂回路を選択する場合があります。 また、 returnToRoute()
のコール によって新しいルートが作成されますが、可能であれば、コストのかかるルートの再計算を行わずに、元のルートからできるだけ類似したルートが作成されます。
- ストップオーバーウェイポイントの通過が保証。
- パススルーウェイポイントは、ルートの形成のみを目的としているため、新しいルートがそれらのルートを受け入れるか、または廃棄するかは保証されない。
- 現在の交通状況が考慮され、ルートが再形成される可能性がある。
ターン・バイ・ターンナビ (矢印ナビ)は Navigate Edition でのみ使用可能。
注
このメソッドreturnToRoute()
は 、キャッシュ、またはダウンロードされたマップ データでオフラインで動作するOfflineRoutingEngine
で使用することもできます。 ただし、現在の交通状況は考慮されません。
returnToRoute()
を 使用したコーディング例については、ナビゲーションの章を参照 してください。
他のサービスからルートをインポート
さまざまな多重定義されたメソッドroutingEngine.importRoute()
のいずれかを使用して、他の API やベンダーからルートをインポートできます。 これは 1 対 1 のインポートフィーチャではなく 、再構築であることに注意してください。
次の場所から新しいRoute
オブジェクトを作成できます。
GeoCoordinates
および RouteOptions
のリスト。 これは、ルートを別のベンダーからインポートする必要がある場合に役立ちます。 -
RouteHandle
は、他の HERE サービスからルートをインポートする場合に役立ちます。 ユースケース では 、 HERE Wego Web サイトまたは HERE REST API を使用する別の Web ページにルートを作成し、それをモバイル機器 に転送して旅程を開始できます。 バックエンド側でのマップの更新、または実世界でのその他の変更によって、無効なハンドルが生じる可能性があります。 そのため、数時間のみハンドルを使用することをお勧めします。 RouteHandle
は特定の情報をエンコードしますが、バックエンドから完全なルートデータを取得するには、オンライン接続が必要です。
適用されたすべてのものAvoidanceOptions
は廃棄され、ルートSection.sectionNotices
を経由して違反として報告されます。 たとえば、高速道路の回避を要求しても、指定された座標が高速道路と一致する場合、導かれたルートは引き続き高速道路と一致しますが、目的の回避オプションに違反していることを示す通知が追加されます。
一般 的に、ルートをインポートすると、元のルートとまったく同じルートが再現されない場合があります。 詳細については、以下を参照してください。
地理座標のリストからルートをインポートします
RouteOptions
GeoCoordinates
のリストからルートをインポートする には、ルートシェイプを定義するGeoCoordinates
のリストが必要です。 このような座標は互いに非常に近い値にする必要があります。そうしないと、計算に失敗します。 このような座標のリストは、別のベンダーによって計算されたルートから抽出することも、 GPX トレースから抽出することもできます。
let routeLocations = [
Location(coordinates: GeoCoordinates(latitude: 52.518032, longitude: 13.420632)),
Location(coordinates: GeoCoordinates(latitude: 52.51772, longitude: 13.42038)),
Location(coordinates: GeoCoordinates(latitude: 52.51764, longitude: 13.42062)),
Location(coordinates: GeoCoordinates(latitude: 52.51754, longitude: 13.42093)),
Location(coordinates: GeoCoordinates(latitude: 52.51735, longitude: 13.42155)),
Location(coordinates: GeoCoordinates(latitude: 52.51719, longitude: 13.42209)),
Location(coordinates: GeoCoordinates(latitude: 52.51707, longitude: 13.42248)),
Location(coordinates: GeoCoordinates(latitude: 52.51695, longitude: 13.42285)),
Location(coordinates: GeoCoordinates(latitude: 52.5168, longitude: 13.42331)),
Location(coordinates: GeoCoordinates(latitude: 52.51661, longitude: 13.42387)),
Location(coordinates: GeoCoordinates(latitude: 52.51648, longitude: 13.42429)),
Location(coordinates: GeoCoordinates(latitude: 52.51618, longitude: 13.42513)),
Location(coordinates: GeoCoordinates(latitude: 52.5161, longitude: 13.42537)),
Location(coordinates: GeoCoordinates(latitude: 52.51543, longitude: 13.42475)),
Location(coordinates: GeoCoordinates(latitude: 52.51514, longitude: 13.42449)),
Location(coordinates: GeoCoordinates(latitude: 52.515001, longitude: 13.424374))]
routingEngine.importRoute(with: routeLocations, carOptions: CarOptions()) { (routingError, routes) in
if (routingError == nil) {
let newRoute = routes?.first
} else {
}
}
このオプションでは、目的の転送タイプに一致するメソッド importRoute()
の過負荷を選択できます。
GeoCoordinates
とRouteOptions
のリストからルートをインポートすると、RoutingEngine
は 提供された地理座標からできるだけ近いルートシェイプを作成します。
座標のリストに制限はありません。 サポートされているアイテムの最大数については、API リファレンスを参照してください。
最適な結果を得るには、 1Hz の GPS データ、または数メートルの間隔を持つポイントを使用します。 データが極端に希薄な場合、エラーが発生する可能性があります。
注 : これはこの機能のベータ版です。
RouteHandle からルートをインポートします
以下のオプションRouteHandle
を参照してください。 RouteHandle(String handle)
コンストラクタを使用すると、指定した文字列ハンドルから RouteHandle
を作成できます。 このような文字列は、利用可能な HERE REST API の 1 つなど、他のバックエンドソースから提供できます。 文字列は数時間のみ有効です。
次に、ルートハンドル文字列を使用してルートを作成する REST API コールの例を示します( YOUR_API_KEY
を使用している実際のキーで置き換えます)。
https://router.hereapi.com/v8/routes?apikey=-YOUR_API_KEY&origin=52.524465%2C13.382334&destination=52.525301%2C13.399844&return=polyline%2Csummary%2Cactions%2Cinstructions%2CrouteHandle&transportMode=car
JSON レスポンスからルートハンドル文字列をコピーし、次のように HERE SDK で使用できます。
routingEngine.importRoute(routeHandle: RouteHandle(handle: "routeHandleStringFromBackend"), refreshRouteOptions: RefreshRouteOptions(CarOptions())) { (routingError, routes) in
if (routingError == nil) {
let newRoute = routes?.first
} else {
}
}
RouteHandle
この文字列は、すでに計算されたルートを示します。 正常にインポートされると、 新しいオブジェクトCalculateRouteCallback
が作成され、Route
の一部として提供され、 HERE SDK でさらに使用できます。
注 : これはこの機能のベータ版です。
ルートをオフラインでインポートします
HERE SDK では、 オフラインでのルートのインポートはサポートされていません。少なくとも、RouteHandle
経由、またはGeoCoordinates
のリストを直接渡すといった上記のような形ではありません。 これは 、オンライン接続が必要なRoutingEngine
でのみ可能です。
ただし、回避策があります。 OfflineRoutingEngine
に無制限の数の Waypoint
アイテムを挿入すると、ルートは指定したストップオーバーウェイポイントでオフラインで計算されることがあり、元のルートにできるだけ近いルートが形成されます。 RoutingEngine
でサポートされるウェイポイントの数は、最大で約 200 個 に制限されていることに注意してください。 OfflineRoutingEngine
を使用する場合 、このような制限はありませんが、ただし、より長いルートではパフォーマンスのトレードオフが発生する可能性があります。 そのため、すべてのルート座標のサブセットのみを経由地 として渡すことをお勧めします。たとえば、距離のしきい値でフィルタリングします。
OfflineRoutingEngine
については、次の章のを参照 してください。 追加のウェイポイント は、オンラインですでに表示されているのと同じ方法 RoutingEngine
で設定できます。
オフラインルーティング
RoutingEngine
に加えて、オフラインの使用例にも相当するものがあります。 OfflineRoutingEngine
:すでに上記で示したオンライン版と同じ方法で構築できます。
private var routingEngine: RoutingProtocol
private var onlineRoutingEngine: RoutingEngine
private var offlineRoutingEngine: OfflineRoutingEngine
...
do {
try onlineRoutingEngine = RoutingEngine()
} catch let engineInstantiationError {
fatalError("Failed to initialize routing engine. Cause: \(engineInstantiationError)")
}
do {
try offlineRoutingEngine = OfflineRoutingEngine()
} catch let engineInstantiationError {
fatalError("Failed to initialize offline routing engine. Cause: \(engineInstantiationError)")
}
routingEngine = onlineRoutingEngine
setNetworkUpdateHandler()
注
トランジットルート(経由 TransitRoutingEngine
)、タクシー(TaxiOptions
)、 EV ルート(EVCarOptions
および EVTruckOptions
) はまだサポートされておらず、オンラインでのみ利用できます。 サポートされていない転送モードの場合、OfflineRouteEngine
は RoutingError.invalidParameter
で失敗します。
OfflineRoutingEngine
は RoutingEngine
と同じインターフェイスを提供しますが、結果は、 HERE バックエンドサービスへの新しい要求を開始するのではなく、すでにダウンロードまたはキャッシュされているマップ データから取得されたものであるため、若干異なる場合があります。
この方法 では、たとえば、RoutingEngine
を使用しているときに受信したデータよりも古いデータを使用できます。 一方、このクラスでは、オンライン接続が不要なため、より迅速に結果を提供します。
ただし、結果のルートには空の操作のリストのみが含まれます。 ガイダンス中に操作が必要な場合は、Navigator
またはVisualNavigator
で提供されているnextManeuverIndex
を経由して直接操作を行うことができます。 これは ナビゲーション セクションに表示されます。
注
すでにキャッシュされているか、または事前にロードされているオフライン地図データでのみルートを計算できます。 キャッシュされたマップ データのみを使用する場合、すべてのタイルが下のズームレベルでロードされているわけではありません。 この場合、マップが表示されていても、低いズームレベルもロードされるまでルートは見つかりません。 オフラインの地図では、この問題は発生しません。また、必要なマップ データがダウンロードした地域で利用可能であることが保証されます。 したがって、キャッシュされたマップ データに依存しないことをお勧めします。
OfflineRoutingEngine
の使用可能なすべてのインターフェイス もRoutingEngine
で使用でき 、両方のエンジンが同じプロトコルを採用します。 以下に示すように、両方のエンジンインスタンスを簡単に切り替えることができます。
注
このすべての動作の概要を確認 するには、オフラインの RoutingExample クラスを参照してください。 以下に示すすべてのコードスニペットが含ま れています。このコードスニペットは、 GitHub にある RoutingHybrid サンプルアプリの一部です。
以下に、OfflineRoutingEngine
とRoutingEngine
を切り替える方法を示します 。 たとえば、移動中に、接続が一時的に失われ可能性があります。 このような場合 は、OfflineRoutingEngine
ですでにキャッシュまたはダウンロードされているマップ データのルートで計算することが妥当です。
そのためには、まずデバイスの接続が失われていないかを確認する必要があります。 2 番目のステップとして、優先エンジンを使用できます。
private func setRoutingEngine() {
if isDeviceConnected {
routingEngine = onlineRoutingEngine
} else {
routingEngine = offlineRoutingEngine
}
}
HERE では isDeviceConnected
、デバイスが接続されているかどうかにかかわらず、ブール型値を使用して保存します。
現在 routingEngine
のインスタンスで同じコードを実行できるようになりました ( 前のセクションを参照 ) 。
注
デバイスがオフラインの場合、オンラインバリアントはルートを検索せず、エラーを報告します。 その逆も同様です。デバイスがオンラインで、使用したい領域にキャッシュまたはプリロードされたマップ データがない場合、オフラインバリアントもエラーを報告します。
デバイスがオンラインかどうかを確認するコードが HERE から削除されていることに注意してください。 この目的でサードパーティの API を使用するか、実際の接続を試みることができます。その場合は OfflineRoutingEngine
、次のようにして - または別の方法に切り替えることができます。 まずオフラインルーティングを試して、ユーザーに高速なエクスペリエンスを提供できますが、マップ データが利用できない場合はオンラインで試すことができます。
注
RoutingHybrid サンプルアプリは 、 GitHub にあります。
ウェイポイントの順番の最適化
OfflineEngine
( 上記を参照 ) では、オフラインのウェイポイントシーケンス を使用して、出張の営業担当者 のユースケース をサポートすることもできます。 このフィーチャーは、オンラインRoutingEngine
ではまだサポートされて いません。
Waypoint
に含まれる複数のストップオーバーアイテム Route
は、次の設定 RouteOptions.optimizeWaypointsOrder
により自動的に順番が決められます。 true
に設定さ れている場合、OfflineRoutingEngine
は、目的地に高速に到達するようにウェイポイントの順序を最適化するか、またはルートを短縮するように試行します。また、すべてのタイプstopover
の設定されたウェイポイント に到達するようにします。
指定されたOptimizationMode
による並べ替えの結果、ルートの速度が速くなるか、または短くなるかが決定されます。
ルート計算への影響を確認するには、少なくとも 5 つ以上のウェイポイント(出発地点と目的地を含む)を設定する必要があります。 必要に 応じて、 各RoutePlace
のoriginalCoordinates
をユーザー定義の座標と比較することで、再シャッフルされたウェイポイントを特定できます。 ストップオーバーごとにルートがセクションに分割されるため、Route
オブジェクトの各RoutePlace
Section
オブジェクトに提供されます。 ナビゲーション中に 、ユーザー定義のウェイポイントに到達したかどうかがイベントMilestoneStatus
によって通知されます。
図 : ウェイポイントシーケンスを使用するルートとしないルート。 これはこのフィーチャーのベータ版です。
到達可能エリアの表示
Isoline(等値線) ルーティングを使用すると、時間、距離、またはエネルギー消費量に基づいて、特定のポイントからの到達範囲を表すポリゴンを生成できます。 ポリゴンには、特定の時間、最長走行距離、電気自動車で利用できる充電レベルで到達できるすべての目的地が含まれます。
注
Isoline(等値線) ルーティング では、リアルタイムおよび履歴のトラフィックが計算で考慮されます。
これがどのように役立つかの例を次に示します。
- 現在地から徒歩2km以内のレストランを検索できます。
- ユーザーは、観光地までの距離に基づいてホテルを検索 できます。たとえば、ディズニーワールドやユニバーサルスタジオなど、アメリカのオーランドにある主なアトラクションまで車で 20 分以内の距離にあるホテルを検索できます。
以下に、電気自動車シナリオの消費量ベースIsoline
の例を示します。この例では、ドライバーが指定された制限値 400 Wh 以内に到達可能なポイントを確認したいと考えています。 そのため、目標は 400 Wh 以下を消費することです。問題は次のとおりです。 このエネルギー制限の範囲内で、ドライバーはどこに達することができますか?
注
電気自動車は、現在のバッテリー充電量と、道路の勾配や補助電源の使用状況などのエネルギー消費量に影響を与える要因に基づいて、到達可能エリアに限界があります。 そのため、適切な範囲を視覚化して、充電ポイントに到達する前のエネルギー不足を避けることができます。 車両には固有の燃費パラメータがあるため、正確な走行距離を計算するために、要求に応じてパラメータを指定する必要があります。 詳細については 、以下の電気自動車のセクションを参照してください。
結果は GeoPolygon
マップに表示できる図形になり、ドライバーに視覚的な方向を提供します。
let calculationOptions = IsolineOptions.Calculation(rangeType: .consumptionInWattHours, rangeValues: [400])
let isolineOptions = IsolineOptions(calculationOptions: calculationOptions,
evCarOptions: getEVCarOptions())
routingEngine.calculateIsoline(center: Waypoint(coordinates: startGeoCoordinates),
isolineOptions: isolineOptions) { (routingError, isolines) in
if let error = routingError {
self.showDialog(title: "Error while calculating reachable area:", message: "\(error)")
return
}
let isoline = isolines!.first!
for geoPolygon in isoline.polygons {
let fillColor = UIColor(red: 0, green: 0.56, blue: 0.54, alpha: 0.5)
let mapPolygon = MapPolygon(geometry: geoPolygon, color: fillColor)
self.mapView.mapScene.addMapPolygon(mapPolygon)
self.mapPolygonList.append(mapPolygon)
}
}
これにより、電気自動車が 400Wh 以下の電力を消費して到達できるエリアが見つかります。その一方で、最短ルートを開始地点から任意の直進方向に走行しようとします。
最速の理由 これは、ルートの最適化モードによって異なります(前述のセクションで説明しました)。もちろん、任意のモードを指定できます。 各 Isoline(等値線) には、出発地点からちょうど 1 つのセンターポイントが必要です。
エネルギー消費に関心があるので、こちら EVCarOptions
も提供しました。 これらのオプションには 、以下の電気自動車の取り回しのセクションに示されているバッテリーの仕様が含まれている必要があります。 範囲タイプとして時間または距離の制限を指定する場合は、前述のように通常のルートオプションを指定できます。
IsolineRangeType
は、提供範囲値のタイプを定義します。 ここでは、400を使用しています。 複数の値を指定できます。その結果、指定された範囲の値ごとに、複数の Isoline
オブジェクトが取得されます。
一方、各オブジェクト Isoline
には、到達範囲に島が含まれている場合など、特殊なケースで複数のポリゴンを含めることができます。 このような領域は、個別のポリゴンとして提供されます。
結果のポリゴンシェイプは、パラメーター maxPoints
で定義できます。 GeoPolygon
の頂点の数を指定します。 このパラメータは、ポリゴンの実際の計算には影響を与えず、その外観にのみ影響します。
スクリーンショット: 指定した制限での到達範囲を表示。 スクリーンショットには、大きな緑色の円で示されたポリゴンの中心位置が表示されます。 また、このエリアを超える可能性のあるルートが表示され、ルートに沿って 2 つの追加の充電ステーションが見つかります。 次のセクションでは、電気自動車のルートを計算する方法について説明します。
注
上記のコードスニペットは、 GitHub にある EVRouting
のサンプルアプリとして見つけることができます。
電気自動車のルートを取得
電気自動車( EV )の使用数と販売量は世界中で増加し続けています。 HERE はどのように電気自動車に最適なルートを提供するのに役立ちますか?
-
HERE EV ルーティングは、 EV が A から B に到達できるように最適化されたルートを提供し、充電の停止回数を最小限に抑え、バッテリー充電時間を最適化します(車両の消費モデルに基づきます)。 また、地形、道路のジオメトリ、リアルタイムの交通情報、交通パターンなど、旅程を計画する際にもいくつかの要因が考慮されます。
-
HERE は、ルート沿いの充電ステーションを検索する代わりに、可能なすべてのステーションの充電時間を分析し、最短の運転時間と充電時間を提供する最適な組み合わせを選択します。
EV ルートの取得は簡単です。 自動車やトラックのルートを取得する場合と同様 に、電気自動車に固有のルートオプションを追加するだけで、 EV のルートを取得できます。 このようにして、電気自動車のルートを他のトランスポートモードと同じように取得できます。 EVRouteOptions
を指定して メソッドcalculateRoute()
に追加するだけです。
routingEngine.calculateRoute(with: [Waypoint(coordinates: startGeoCoordinates!),
Waypoint(coordinates: destinationGeoCoordinates!)],
evCarOptions: getEVCarOptions()) { (routingError, routes) in
if let error = routingError {
self.showDialog(title: "Error while calculating a route:", message: "\(error)")
return
}
}
デフォルトでは、EVRouteOptions
は、エネルギー不足なしで目的地に到達できるようにするために必要なパラメータを含んでいません。
これを確実 に行うには、ルートにチャージステーションを追加するために必要なパラメータを設定する必要があります。また、全体的な移動時間の結果を最適化する必要があります。
以下に、このようなオプションの作成例を示します。
private func getEVCarOptions() -> EVCarOptions {
var evCarOptions = EVCarOptions()
evCarOptions.consumptionModel.ascentConsumptionInWattHoursPerMeter = 9
evCarOptions.consumptionModel.descentRecoveryInWattHoursPerMeter = 4.3
evCarOptions.consumptionModel.freeFlowSpeedTable = [0: 0.239,
27: 0.239,
60: 0.196,
90: 0.238]
evCarOptions.routeOptions.alternatives = 0;
evCarOptions.ensureReachability = true
evCarOptions.avoidanceOptions = AvoidanceOptions()
evCarOptions.routeOptions.speedCapInMetersPerSecond = nil
evCarOptions.routeOptions.optimizationMode = .fastest
evCarOptions.batterySpecifications.connectorTypes = [.tesla, .iec62196Type1Combo, .iec62196Type2Combo]
evCarOptions.batterySpecifications.totalCapacityInKilowattHours = 80.0
evCarOptions.batterySpecifications.initialChargeInKilowattHours = 10.0
evCarOptions.batterySpecifications.targetChargeInKilowattHours = 72.0
evCarOptions.batterySpecifications.chargingCurve = [0: 239.0,
64: 111.0,
72: 1.0]
return evCarOptions
}
HERE では、 電気自動車のエネルギー消費モデルEVConsumptionModel
を指定するようにを定義します。 また、BatterySpecifications
を追加します 。 これらのオプションを使用すると、追加のストップオーバーとして追加のチャージステーションをルートに挿入できます。つまり、挿入されたチャージステーションの数に応じて、ルートがより多くのセクションに分割されます。
注
このように必要な充電ステーションを含める場合は、必ずOptimizationMode.fastest
を使用してください。 また、ensureReachability
を true に設定する必要があります。 ensureReachability
がアクティブ化 されている場合、必要な充電ステーションが結果の経路に沿って移動し、必要な充電ステーションがroute
にWayPoint
アイテムとして追加されるようにルートを調整できます。
すべてのオプションが、電気自動車のルートの計算にかかる時間に影響を与える可能性があります。 最も重要なのは、totalCapacityInKilowattHours
に設定されている大容量のバッテリーでは、充電の停止や、旅程開始時のフル充電のバッテリーの必要性が低減されることです。詳細については、以下のinitialChargeInKilowattHours
を参照してください。 比較的低い値は、ルートの先頭付近に充電ステーションが含まれている必要があることを意味します。 そうしないと、ルートの計算に失敗する可能性があります。
現在、エンジンには サービス中の充電ステーションのみが含まれています。 アウトオブサービスまたはメンテナンス中のチャージステーションは考慮されません。 ただし、チャージステーションは動的な状況のため、エンジンは、ステーションが現在使用中または予約済みであるかどうかは判断しません。 最悪の場合、充電ステーションに到着したときに、他の車を充電するために、現在使用されている可能性があります。
また、利用可能なバッテリーコネクタタイプも指定しているため、車両を充電するための互換性のあるコネクタを提供していない充電ステーションは除外されます。
注
通常、バッテリーの消費量とバッテリーの情報は車自体から取得するか、マニュアルまたは自動車メーカーに直接問い合わせることで取得可能です。すべての情報が利用できるわけではありません。また、一部の情報はメーカーのみが把握している場合があります。 いずれの場合も、ルート計算プロセスでは指定された仕様が考慮され、不足している値に適切なデフォルト値が入力されます。
特に電気自動車を使用した長距離ドライブの場合は、途中で充電の停止を計画することが重要です。 結局のところ、チャージステーションはガソリンスタンドよりもはるかに一般的ではありません。 上記のオプションを使用する と、RoutingEngine
は最速のルート(すなわち、目的地に到達するために消費された全体的な時間が最も短いルート)を探し、その間に車両のエネルギーが不足しないようにします。
この計算結果は、「 ルートに沿った検索 」セクションに示されているように、電気自動車向けに最適化されたルートです。経路に沿って見つかった充電ステーションを追加するだけではありません。
route
が計算されると、より有用な情報を収集できます。 以下のコード スニペットには、Section
ごとの推定エネルギー消費量が記録され、 必要に応じてバッテリーを充電するために必要な処置が一覧表示されます。
let additionalSectionCount = route.sections.count - 1
if (additionalSectionCount > 0) {
print("Number of required stops at charging stations: \(additionalSectionCount)")
} else {
print("Based on the provided options, the destination can be reached without a stop at a charging station.")
}
var sectionIndex = 0
let sections = route.sections
for section in sections {
let evDetails = section.evDetails
print("Estimated net energy consumption in kWh for this section: \(String(describing: evDetails?.consumptionInKilowattHour))")
for postAction in section.postActions {
switch postAction.action {
case .chargingSetup:
print("At the end of this section you need to setup charging for \(postAction.duration) s.")
break
case .charging:
print("At the end of this section you need to charge for \(postAction.duration) s.")
break
case .wait:
print("At the end of this section you need to wait for \(postAction.duration) s.")
break
default: fatalError("Unknown post action type.")
}
}
print("Section \(sectionIndex): Estimated battery charge in kWh when leaving the departure place: \(String(describing: section.departurePlace.chargeInKilowattHours))")
print("Section \(sectionIndex): Estimated battery charge in kWh when leaving the arrival place: \(String(describing: section.arrivalPlace.chargeInKilowattHours))")
let depStation = section.departurePlace.chargingStation
if depStation != nil && !chargingStationsIDs.contains(depStation?.id ?? "-1") {
print("Section \(sectionIndex), name of charging station: \(String(describing: depStation?.name))")
chargingStationsIDs.append(depStation?.id ?? "-1")
addCircleMapMarker(geoCoordinates: section.departurePlace.mapMatchedCoordinates, imageName: "required_charging.png")
}
let arrStation = section.departurePlace.chargingStation
if arrStation != nil && !chargingStationsIDs.contains(arrStation?.id ?? "-1") {
print("Section \(sectionIndex), name of charging station: \(String(describing: arrStation?.name))")
chargingStationsIDs.append(arrStation?.id ?? "-1")
addCircleMapMarker(geoCoordinates: section.arrivalPlace.mapMatchedCoordinates, imageName: "required_charging.png")
}
sectionIndex += 1
}
postAction.duration
には、バッテリの充電にかかる推定時間が秒単位で示されています。 この時間は、全体的なルート計算および到着予定時間( ETA )に含まれます。
以下は、導かれるルートのスクリーンショットです。
スクリーンショット: 電気自動車のルートを表示。 HERE ルートには、充電スタンドで 2 つのウェイポイントが必要であることがわかります。赤色のマーカーで示されます。 このため、ルートに は、各充電スタンドが追加のウェイポイントを挿入するときにルートを分割するための 3 つのセクションが含まれています。
最初のセクションに は、充電の停止について説明する事後処理が含まれています。 これには、予想到着料金などの情報が含まれています。
特に指定のない限り、エネルギー消費量は Wh と見なされます。
消費モデルを定義
以下のパラメータは、電気自動車のより正確な結果を得るための消費モデルを定義します。
- ascentConsumptionInWattHoursPerMeter: 1 メートルあたりのエネルギー消費量の上昇率。
- PercentRecoveryInWattHoursPerMeter : 1 メートル降下する毎のエネルギー回収の割合。
- freeFlowSpeedTable: 平坦な舗装路で、所定のフリーフロー速度での消費レートを指定する機能カーブ。
- trafficSpeedTable: 平坦な道路での交通状況下で、所定の速度での消費レートを指定する機能カーブ。
- auxiliaryConsumptionInWattHoursPerSecond : 車両の補助システム(エアコン、照明など)が 1 秒間に消費するエネルギーの割合。
消費速度表は、車両が km/時 で指定された速度で標高の変更を行うことなく直進路を走行するときのエネルギー消費量を定義する。 区分線形関数を表します。
HERE は、フリーフロー速度リストの例です。 左側には速度が、右側には燃費が表示されます。
- 0 : 0.239.
- 27 : 0.239.
- 45 : 0.259.
- 60 : 0.196.
- 75 : 0.207.
- 90 : 0.238.
- 100 : 0.26
- 110 : 0.296
- 120 : 0.337
- 130 : 0.351
グラフでは、次のようになります。
スクリーンショット: 燃費グラフの例。 2 つの異なる消費速度テーブル(フリーフロー速度テーブル と トラフィック速度テーブル)を指定できます。
- フリーフロー速度: 一定の速度で走行する場合のエネルギー消費量を示します。
- 走行速度: 交通量の多い状況で走行する場合のエネルギー消費量を示します。たとえば、車両が特定の平均速度で走行速度を頻繁に変更すると予想される場合などです。
trafficSpeedTable
が提供されていない場合 は、速度関連のエネルギー消費量の計算にのみfreeFlowSpeedTable
が使用されます。
注
GitHub でEVRouting
サンプルのアプリを見つける ことができます。