Powered by Zoomin Software.詳細については、以下までお問い合わせくださいZoomin

HERE SDK for Android Explore - 開発者ガイド

製品カテゴリ
テクノロジー
ドキュメント タイプ
バージョン
製品ライフサイクル
本書

HERE SDK for Android Explore - 開発者ガイド: ルート検索を開始する

フィードバック
印刷
目次
ホームHERE SDK for Android Explore - 開発者ガイドルート検索を開始する現在のページ
目次

ルート検索を開始する

フィードバック
印刷

HERE SDK では、A 地点から B 地点までの最適なルートを計算する本格的な RoutingEngine が用意されており、複数の経由地設定やローカライズ可能な右左折ごとの運転指示などの機能が含まれています。

希望のルート タイプ (最速または最短) とさまざまなルート オプション (速度プロファイル、ルート制限、ビネット オプションなど) を設定して優先設定を指定することで、最もエネルギーを節約できる最適なルートを見つけることができます。HERE は、高度なルート検索技術と専用の EV ルート プランニング サポートにより、地球をよりクリーンで安全なものにするお手伝いをします。

機能の概要:

  • ルートを計算する:さまざまな移動モードで複数の経由地を使用してルートを計算します。
  • Isoline Routing:時間、距離、または燃料消費量に基づいて、特定のポイントからの到達範囲を表す等値線ポリゴンを計算します。
  • ルートに沿って検索する:ルート全体に沿って場所を検索します (この機能については「検索」セクションで説明します)。
  • ルート インポート/ルートの照合:他の API からルートをインポートできます。

RoutingEngine を初期化する

次の方法でルート エンジンを作成して移動を開始します。

try {
    routingEngine = new RoutingEngine();
} catch (InstantiationErrorException e) {
    throw new RuntimeException("Initialization of RoutingEngine failed: " + e.error.name());
}

新しい RoutingEngine インスタンスを作成すると、前述のように処理する必要のあるエラーがスローされる場合があります。たとえば、HERE SDK の初期化が事前に失敗した場合にこのようなエラーが発生する可能性があります。

ApplicationonCreate() メソッド中にこのエンジンを初期化することはできません。それ以外の時点であれば問題ありません。たとえば、このエンジンを初期化するのに適した場所が ActivityonCreate() メソッドに含まれている可能性があります。

ルートを計算する

次のステップとして、出発地と目的地 (どちらも GeoCoordinates インスタンスを保持する Waypoint タイプ) の 2 つの経由地に基づいてルートを計算できます。以下では、乗用車に合わせて最適化されたルートを計算するためにデフォルトの CarOptions を設定します。

Waypoint startWaypoint = new Waypoint(startGeoCoordinates);
Waypoint destinationWaypoint = new Waypoint(destinationGeoCoordinates);

List<Waypoint> waypoints =
        new ArrayList<>(Arrays.asList(startWaypoint, destinationWaypoint));

routingEngine.calculateRoute(
        waypoints,
        new CarOptions(),
        new CalculateRouteCallback() {
            @Override
            public void onRouteCalculated(@Nullable RoutingError routingError, @Nullable List<Route> routes) {
                if (routingError == null) {
                    Route route = routes.get(0);
                    showRouteDetails(route);
                    showRouteOnMap(route);
                    logRouteViolations(route);
                } else {
                    showDialog("Error while calculating a route:", routingError.toString());
                }
            }
        });

calculateRoute() は複数回呼び出すことができます。たとえば、さまざまなルート検索オプションを使用して複数のルートを並行して計算するために呼び出すことができます。

Waypoint を設定するときに sideOfStreetHint を設定することで、歩行者またはドライバーが停車地に到着するときに道路のどちら側になるか調整できます。

歩行者またはドライバーが移動している場合、startWaypoint.headingInDegrees = location.bearingInDegrees; を設定することで、方位値によって最初の進行方向が決定されます。これにより、次の目的地がドライバーの後方にある場合に不要な U ターンを回避できます。歩行者は、これにより道路を横断する必要がなくなるので、より良いルートを確保することができます。

各ルート計算は非同期で実行されます。完了すると Route リストか、エラーがあったときにエラーを示す RoutingError を取得します。すべてうまくいけば RoutingError は NULL になります。エラーが発生した場合、ルート リストは NULL になります。たとえば、指定された移動モードでルートが実行可能でない場合、エンジンでルートを計算できません。

エラーがなければ、ルート リストには結果が 1 つだけ含まれます。ルート オプションを使用して代替ルートの数を指定すると、追加のルート バリエーションをリクエストできます。デフォルトでは、代替ルートなしでルートが計算されます。

上記のコード スニペットの showRouteDetails() メソッドを使用して、運転指示を含むルートの詳細を表示します。完全なソース コードは付属のサンプル アプリで確認できます。運転指示については以下でも詳しく説明します。showRouteOnMap() メソッドには、マップ上でルートをレンダリングする方法の例が含まれています。この点については、後述のセクションで簡単に説明します。

ETA および交通情報を取得する

目的地までの移動にかかる推定時間 (ETA) やルートの全長 (メートル単位) など、ルートに関する追加情報は以下のように Route オブジェクトから取得できます。

// estimatedTravelTimeInSeconds includes traffic delay.
long estimatedTravelTimeInSeconds = route.getDuration().getSeconds();
long estimatedTrafficDelayInSeconds = route.getTrafficDelay().getSeconds();
int lengthInMeters = route.getLengthInMeters();

到着予定時刻 (ETA) は、デバイスの地理座標によって異なるタイムゾーンで表示できます。たとえば、ルートを計算するとき、デバイスの現在のタイム ゾーンが目的地のタイム ゾーンと異なる場合があります。ベルリンからロンドンまでのルートを計算するシナリオを考えてみましょう。各都市は異なるタイム ゾーンに従っています。これに対処するため、ETA を複数のタイム ゾーンで表示できます。デバイスの現在のタイム ゾーン (ベルリン)、目的地のタイム ゾーン (ロンドン)、またグローバル リファレンスとして UTC (協定世界時) を設定します。

同じ ETA が異なるタイム ゾーン間でどのように変化するかの例は次のとおりです。

デバイスの現在のタイム ゾーン (ベルリン) に基づく ETA デバイスの目的地のタイム ゾーン (ロンドン) に基づく ETA UTC での ETA
8:30 AM 7:30 AM 6:30 AM

デバイスのタイム ゾーンで ETA を計算するには、次の方法を使用します。この方法では、Route オブジェクトから推定移動時間を取得し、現在の日付と時刻を初期化して、移動時間を追加し、結果の形式を設定します。

/**
 * Returns the ETA (as a string in ‘HH:mm’ format) in the current device’s timezone, derived from the estimatedTravelTimeInSeconds, which is sourced from the Route object.
 *
 * @param route Original route object from RoutingEngine.
 * @return A string representing the ETA in "HH:mm" format.
 */
public String getETAinDeviceTimeZone(Route route) {
    long estimatedTravelTimeInSeconds = route.getDuration().toSeconds();

    // Get an instance of the Calendar class initialized with the current date and time
    Calendar calendar = Calendar.getInstance();

    // Set the calendar's time to the current date and time
    calendar.setTime(new Date());

    // Add the estimated travel time (in seconds) to the current time
    calendar.add(Calendar.SECOND, (int) estimatedTravelTimeInSeconds);

    return getFormattedDate(calendar.getTime());
}

目的地のタイム ゾーンの ETA を計算するには、次の方法を使用します。この方法では、到着地の現地時間と、目的地の現地時間と協定世界時 (UTC) の差を取得します。

/**
 * Calculates the estimated time of arrival (ETA) in the destination timezone for a given route.
 * It is possible that the destination can be in a different timezone compared to the source.
 * Therefore, we are also calculating the ETA in the destination timezone. For example, the source can be in Berlin and the destination can be in Dubai.
 *
 * @param route Original route object from RoutingEngine.
 * @return A string representing the estimated time of arrival in the destination timezone, formatted as "hh:mm".
 */
public String getETAinDestinationTimeZone(Route route) {
    LocationTime arrivalLocationTime = getArrivalLocationTime(route);
    Date destinationDate = arrivalLocationTime.localTime;

    // The timeOffset represents the difference between the local time at destination and Coordinated Universal Time (UTC) in minutes.
    int timeOffset = (int) arrivalLocationTime.utcOffset.toMinutes();

    return getFormattedDate(destinationDate, timeOffset);
}

特定のルートでの ETA を協定世界時 (UTC) で計算するには、次の方法を使用します。この方法では、世界時間として規定される一時標準時で ETA が表されます。


/**
 * Calculates the estimated time of arrival (ETA) in Coordinated Universal Time (UTC) for a given route.
 * UTC (Coordinated Universal Time) is the primary time standard by which the world regulates clocks and time.
 *
 * @param route Original route object from RoutingEngine.
 * @return A string representing the estimated time of arrival in UTC, formatted as "HH:mm".
 */
public String getEstimatedTimeOfArrivalInUTC(Route route) {
    Date utcDate = getArrivalLocationTime(route).utcTime;

    // The UTC offset represents the difference in hours and minutes between a specific time zone and Coordinated Universal Time (UTC).
    // It indicates whether the local time is ahead (+) or behind (-) UTC.
    // By using an offset of 0, we ensure that the time being represented is in Coordinated Universal Time (UTC).
    int utcTimeOffset = 0;
    return getFormattedDate(utcDate, utcTimeOffset);
}

getArrivalLocationTime(Route route) メソッドは、ルートの最終セクションから特定のルートの到着時刻を取得します。ルート内の各セクションの所要時間を順番に累算します。たとえば、5 分かかるセクションが 2 つある場合、最初のセクションの所要時間は 5 分、2 つ目のセクションの合計所要時間は 10 分 (各セクションで 5 分) です。

// Returns the arrival time at the final location of the route.
private LocationTime getArrivalLocationTime(Route route) {
    int lastSectionIndex = route.getSections().size() - 1;

    // The lastSection contains cumulative duration values that increase sequentially.
    // For instance, if there are two sections, each with a duration of 5 minutes, the first section will reflect a total duration of 5 minutes,
    // while the second section will show a total duration of 10 minutes.
    // This is because the total time includes the initial 5 minutes for the first section, followed by an additional 5 minutes to complete the second section, resulting in a cumulative travel time.
    Section lastSection = route.getSections().get(lastSectionIndex);
    return lastSection.getArrivalLocationTime();
}

上記の ETA を特定のタイム ゾーンでフォーマットする方法は次のとおりです。

/**
 * Formats the given date to a string representation based on the specified timezone offset.
 *
 * @param date   The Date object to be formatted.
 * @param offset The UTC offset in minutes for the desired timezone.
 * @return A string representing the formatted time in the specified timezone.
 */
private String getFormattedDate(Date date, int offset) {
    // Create a DateFormat instance that formats the time in a short format (e.g., "HH:mm a").
    java.text.DateFormat dateFormat = SimpleDateFormat.getTimeInstance(java.text.DateFormat.SHORT);

    // Retrieve the TimeZone object corresponding to the given UTC offset.
    TimeZone timeZone = getTimeZone(offset);

    // Set the DateFormat's timezone to the retrieved TimeZone.
    dateFormat.setTimeZone(timeZone);

    // Format the date using the configured DateFormat and return the result as a string.
    return dateFormat.format(date);
}

/**
 * Formats the given date to a string representation using the device's default timezone.
 *
 * @param date The Date object to be formatted.
 * @return     A string representing the formatted time in the default timezone.
 */
private String getFormattedDate(Date date) {
    // Create a DateFormat instance that formats the time in a short format (e.g., "HH:mm a").
    java.text.DateFormat dateFormat = SimpleDateFormat.getTimeInstance(java.text.DateFormat.SHORT);

    // Format the date using the configured DateFormat and return the result as a string.
    return dateFormat.format(date);
}

/**
 * Retrieves a TimeZone object based on the given UTC offset in minutes.
 *
 * @param utcOffsetInMinutes The UTC offset in minutes (can be positive or negative).
 * @return A TimeZone object representing the specified offset from GMT.
 */
private TimeZone getTimeZone(int utcOffsetInMinutes) {
    // Calculate the offset in hours.
    int hours = utcOffsetInMinutes / 60;

    // Calculate the remaining offset in minutes after converting to hours.
    int minutes = utcOffsetInMinutes % 60;

    // Create a string representing the time zone in GMT format (e.g., "GMT+05:30").
    String timeZoneId = String.format("GMT%+03d:%02d", hours, minutes);

    // Retrieve and return the TimeZone object corresponding to the constructed GMT time zone ID.
    return TimeZone.getTimeZone(timeZoneId);
}

交通状況に関するより詳細な情報は、ルートの個々のセクションで利用できます。Route の各 Section には、運転操作 (上記を参照) に加えて、ルートが計算された時点の交通流状況の情報が含まれています。

Section には、さまざまな量の TrafficSpeed インスタンスを含めることができます。これらは、Span に沿って次の Span まで有効です。各 Span ジオメトリーは、ルート全体のポリライン形状の一部であるポリラインで表されます。

次のコード スニペットは、Section の最初の SpanTrafficSpeed 要素を取得する方法を示しています。

Section firstSection = route.getSections().get(0);
TrafficSpeed firstTrafficSpeed = firstSection.getSpans().get(0).getTrafficSpeed();

TrafficSpeed には、予想されるデフォルトの移動速度である baseSpeedInMetersPerSecond が含まれています。これは、道路の現在の制限速度と同じではない場合があることに注意してください。道路状況が悪い場合は、より遅い移動速度が妥当である場合があります。さらに、trafficSpeedInMetersPerSecond を使用すると、現在の交通状況に基づいて推定される実際の移動速度を取得できます。

refreshRoute() 経由でルートを更新すると、ルートの交通情報を更新できます。

今後の制限速度などを確認する

Route オブジェクトは、Route に沿った詳細情報を公開して、今後の制限速度、道路の属性と道路名、踏切、動的な交通情報などを把握します。

次の属性を見てみましょう:Span.sectionPolylineOffsetSpan.dynamicSpeedInfoSpan.streetAttributesSpan.carAttributesSpan.truckAttributesSpan.scooterAttributesSpan.walkAttributesSpan.durationInSecondsSpan.streetNamesSpan.routeNumbersSpan.speedLimitInMetersPerSecondSpan.consumptionInKilowattHoursSpan.functionalRoadClassSpan.durationSpan.baseDuration。属性の完全なリストについては、「API リファレンス」を参照してください。

各属性はスパンごとに指定され、スパン全体の長さに対して有効です。場合によっては、2 つの交差点間の道路ネットワークの一部を示すセグメント ID が見つかることもあります。Span はルート関連の概念で、同じ属性を持つルートの一部です。同じセグメント上に複数のスパンが存在する場合があり、通常、各セグメントには開始オフセットと終了オフセットがあります。

Span はルート セグメントの最小部分を定義し、そのカーブは GeoCoordinates のリストとして公開されます。

踏切情報を取得する

RouteRailwayCrossing のリストは Route オブジェクトから取得できます。このオブジェクトには、踏切の GeoCoordinatesRouteOffset、ルートを横断する鉄道路線または路面電車路線の RouteRailwayCrossingType の情報が含まれます。

RouteOffset とはセクション インデックスによって定義されるルート上の位置であり、そのセクションの始点からルート上の指定された位置までの距離 (メートル単位) のことです。 RouteOffset の詳細については、「APIリファレンス」を参照してください。

RouteRailwayCrossing の使用例を以下に示します。

for (RouteRailwayCrossing routeRailwayCrossing : route.getRailwayCrossings()) {
    // Coordinates of the route offset
    GeoCoordinates routeOffsetCoordinates = routeRailwayCrossing.coordinates;
    // Index of the corresponding route section. The start of the section indicates the start of the offset.
    int routeOffsetSectionIndex = routeRailwayCrossing.routeOffset.sectionIndex;
    // Offset from the start of the specified section to the specified location along the route.
    double routeOffsetInMeters = routeRailwayCrossing.routeOffset.offsetInMeters;

    Log.d(TAG, "A railway crossing of type " + routeRailwayCrossing.type.name() +
        "is situated " +
        routeOffsetInMeters + " m away from start of section: " +
        routeOffsetSectionIndex);
}

ルート違反を検出する

ルートには、ルートの計算後に発生する可能性のある問題を説明する NoticeCode 値のリストが含まれている場合があります。たとえば、ルートでトンネルを回避する必要があり、唯一のルート候補でトンネルを通過する必要がある場合、Route には、リクエストされたトンネル回避の違反があったことを示す通知が含まれます。

  • 計算済みの Route に違反の可能性がないか必ず確認することをお勧めします。
  • NoticeCodeNotice オブジェクトの一部です。使用可能な Notice オブジェクトのリストには RouteSection に従ってアクセスできます。
  • 違反が発生していない場合、リストは空になります。
  • 違反の可能性を排除する場合は、違反を 1 つでも含むルートをスキップすることをお勧めします。

ただし、リクエストされたルート オプションおよび実際の NoticeCode 値のリストに応じて、実装はケースバイケースで判断します。ルート オプションの詳細については、次のセクションを参照してください。重要:説明をわかりやすくするため、このガイドのコード スニペットでは通知の列挙型 (enum) 値を評価しません。

次の方法でルート通知を検出できます。

// A route may contain several warnings, for example, when a certain route option could not be fulfilled.
// An implementation may decide to reject a route if one or more violations are detected.
private void logRouteViolations(Route route) {
    for (Section section : route.getSections()) {
        for (Span span : section.getSpans()) {
            List<GeoCoordinates> spanGeometryVertices = span.getGeometry().vertices;
            // This route violation spreads across the whole span geometry.
            GeoCoordinates violationStartPoint = spanGeometryVertices.get(0);
            GeoCoordinates violationEndPoint = spanGeometryVertices.get(spanGeometryVertices.size() - 1);
            for (int index : span.getNoticeIndexes()) {
                SectionNotice spanSectionNotice = section.getSectionNotices().get(index);
                // The violation code such as "VIOLATED_VEHICLE_RESTRICTION".
                String violationCode = spanSectionNotice.code.toString();
                Log.d(TAG, "The violation " + violationCode + " starts at " + toString(violationStartPoint) + " and ends at " + toString(violationEndPoint) + " .");
            }
        }
    }
}

すべてのルートにはルートに沿って高度値が含まれています。たとえば、計画された自転車旅行の標高プロファイルを作成する目的で高度値を使用します。

Routing サンプル アプリを試す

GitHub には、上記のすべてのコード スニペットに加え、その他のコードが含まれる「Routing」サンプル アプリがあります。

GitHub には「PublicTransit」サンプル アプリもあります。TransitRoutingEngine を使用して、A 地点から B 地点までの公共交通機関のルートを計算する方法を示します。A 地点と B 地点の間には複数の経由地があります。

GitHub にある Rerouting サンプル アプリも参照してください。これには Naviate Edition が必要ですが、UI ビルディング ブロックと IconProvider のコードは他のエディションでも使用でき、たとえば、ルート プレビュー パネルの一部として道路標識アイコンを表示できます。

この記事は役に立ちましたか?
TitleResults for “How to create a CRG?”Also Available inAlert