规划路线示例

您可以在 HTTP 请求和响应中使用 ComputeCustomRoutes 方法,也可以与支持 gRPC 的任何语言(包括 Java 和 Go)搭配使用。

HTTP 示例

以下示例演示了 curl 请求和响应的示例。

请求:

curl -X POST -d '{
  "origin":{
    "location":{
      "latLng":{
        "latitude":37.419734,
        "longitude":-122.0827784
      }
    }
  },
  "destination":{
    "location":{
      "latLng":{
        "latitude":37.417670,
        "longitude":-122.079595
      }
    }
  },
  "travelMode":"DRIVE",
  "routingPreference":"TRAFFIC_AWARE",
  "routeObjective": {
    "rateCard":{
      "costPerMinute":{
         "value":1.1
      },
      "costPerKm":{
         "value":2.2
      }
    }
  }
}'
\
-H 'Content-Type: application/json' \
-H 'X-Goog-Api-Key: <YOUR_API_KEY>' \
-H 'X-Goog-FieldMask: routes.route.distanceMeters,routes.route.duration,routes.token,routes.route.travelAdvisory.tollInfo' \
'https://routespreferred.googleapis.com/v1alpha:computeCustomRoutes'

回答:

{
 
"routes": [
   
{
     
"route": {
       
"distanceMeters": 987,
       
"duration": "247s",
       
"travelAdvisory": {
         
"tollInfo": {}
       
}
     
},
     
"token": "CocCCnYKCNOX2XMIWqf2EihazE0WzZ87txlU4F74nQiWxZpgRgOzf3TMHUm1sVpY4APnvf_BWoEYGibs64nuCxYcsQEXqQjaChCLGOkBHNseoyoAmAG1CxbkG58hEhJ4FiIBKkIJbwqHAz2qAhZfSgivvZI-AACAP3gBEAQaigEKhwEKLAohChYIAxISCgcQARiAwtcvEgcQAhiAhK9fEQAAAAAAAPA_EareoBH6vShAEg4IABADEAYYAkIEGgIIBRoGCgQIAhACIj8KNjIwMjAtMDYtMTB8MTI6NTY6MzcuODg3OTEzLTA3fDEwLjk5LjE5OS4xNnwtMTA3Mjc4OTI3MhCHwajvnhs"
   
}
 
]
}

应将 ComputeCustomRoutes 响应中的路线令牌传递给 Navigation SDK 以启动导航会话,该会话会尝试遵循 Routes Preferred API 返回的路线。路线令牌不会过期,但由于道路状况动态变化,使用给定令牌生成的路线可能会与原始路线不同。我们强烈建议您在生成路线令牌后的几分钟内使用该令牌。

如需详细了解路线令牌,请参阅 Navigation SDK for Android 和 Navigation SDK for iOS 文档:

Java 和 Go 示例

以下示例展示了如何使用 Java 或 Go 调用 ComputeCustomRoutes 方法。如需了解构建说明,请参阅相应的 JavaGo Github 代码库。

JavaGo
package com.example;

import com.google.maps.routes.v1.ComputeCustomRoutesRequest;
import com.google.maps.routes.v1.ComputeCustomRoutesResponse;
import com.google.maps.routes.v1.Location;
import com.google.maps.routes.v1.PolylineQuality;
import com.google.maps.routes.v1.RouteModifiers;
import com.google.maps.routes.v1.RouteObjective;
import com.google.maps.routes.v1.RouteObjective.RateCard;
import com.google.maps.routes.v1.RouteObjective.RateCard.MonetaryCost;
import com.google.maps.routes.v1.RouteTravelMode;
import com.google.maps.routes.v1.RoutingPreference;
import com.google.maps.routes.v1.Units;
import com.google.maps.routes.v1.Waypoint;
import com.google.maps.routes.v1alpha.RoutesAlphaGrpc;
import com.google.type.LatLng;
import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientInterceptor;
import io.grpc.ClientInterceptors;
import io.grpc.ForwardingClientCall;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.StatusRuntimeException;
import io.grpc.netty.NettyChannelBuilder;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

public class RoutesPreferredCustomRoutesClient {
 
// For more detail on inserting API keys, see:
 
// https://cloud.google.com/endpoints/docs/grpc/restricting-api-access-with-api-keys#java
 
// For more detail on system parameters (such as FieldMask), see:
 
// https://cloud.google.com/apis/docs/system-parameters
 
private static final class RoutesPreferredInterceptor implements ClientInterceptor {
   
private final String apiKey;
   
private static final Logger logger =
       
Logger.getLogger(RoutesPreferredInterceptor.class.getName());
   
private static Metadata.Key<String> API_KEY_HEADER =
       
Metadata.Key.of("x-goog-api-key", Metadata.ASCII_STRING_MARSHALLER);
   
private static Metadata.Key<String> FIELD_MASK_HEADER =
       
Metadata.Key.of("x-goog-fieldmask", Metadata.ASCII_STRING_MARSHALLER);

   
public RoutesPreferredInterceptor(String apiKey) {
     
this.apiKey = apiKey;
   
}

   
@Override
   
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
       
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
      logger
.info("Intercepted " + method.getFullMethodName());
     
ClientCall<ReqT, RespT> call = next.newCall(method, callOptions);
      call
=
         
new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(call) {
           
@Override
           
public void start(Listener<RespT> responseListener, Metadata headers) {
              headers
.put(API_KEY_HEADER, apiKey);
             
// Note that setting the field mask to * is OK for testing, but discouraged in
             
// production. For example, for ComputeCustomRoutes, set the field mask to
             
// "routes.route.duration,routes.route.distanceMeters,routes.route.polyline"
             
// in order to get the route distances, durations, and encoded polylines.
              headers
.put(FIELD_MASK_HEADER, "*");
             
super.start(responseListener, headers);
           
}
         
};
     
return call;
   
}
 
}

 
private static final Logger logger =
     
Logger.getLogger(RoutesPreferredCustomRoutesClient.class.getName());
 
private final RoutesAlphaGrpc.RoutesAlphaBlockingStub blockingStub;

 
public RoutesPreferredCustomRoutesClient(Channel channel) {
    blockingStub
= RoutesAlphaGrpc.newBlockingStub(channel);
 
}

 
public static Waypoint createWaypointForLatLng(double lat, double lng) {
   
return Waypoint.newBuilder()
       
.setLocation(
           
Location.newBuilder().setLatLng(LatLng.newBuilder().setLatitude(lat).setLongitude(lng)))
       
.build();
 
}

 
public void computeCustomRoutes() {
   
ComputeCustomRoutesRequest request =
       
ComputeCustomRoutesRequest.newBuilder()
           
.setOrigin(createWaypointForLatLng(37.420761, -122.081356))
           
.setDestination(createWaypointForLatLng(37.420999, -122.086894))
           
.setRouteObjective(
               
RouteObjective.newBuilder()
                   
.setRateCard(
                       
RateCard.newBuilder()
                           
.setCostPerMinute(MonetaryCost.newBuilder().setValue(1.1))))
           
.setTravelMode(RouteTravelMode.DRIVE)
           
.setRoutingPreference(RoutingPreference.TRAFFIC_AWARE)
           
.setUnits(Units.METRIC)
           
.setLanguageCode("en-us")
           
.setRouteModifiers(
               
RouteModifiers.newBuilder()
                   
.setAvoidTolls(false)
                   
.setAvoidHighways(true)
                   
.setAvoidFerries(true))
           
.setPolylineQuality(PolylineQuality.OVERVIEW)
           
.build();
   
ComputeCustomRoutesResponse response;
   
try {
      logger
.info("About to send request: " + request.toString());
      response
=
          blockingStub
.withDeadlineAfter(2000, TimeUnit.MILLISECONDS).computeCustomRoutes(request);
   
} catch (StatusRuntimeException e) {
      logger
.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
     
return;
   
}
    logger
.info("Response: " + response.toString());
 
}

 
public static void main(String[] args) throws Exception {
   
String apiKey = System.getenv("GOOGLE_MAPS_API_KEY");

   
// The standard TLS port is 443
   
Channel channel = NettyChannelBuilder.forAddress("routespreferred.googleapis.com", 443).build();
    channel
= ClientInterceptors.intercept(channel, new RoutesPreferredInterceptor(apiKey));

   
RoutesPreferredCustomRoutesClient client = new RoutesPreferredCustomRoutesClient(channel);
    client
.computeCustomRoutes();
 
}
}
 
package main

import (
       
"context"
       
"crypto/tls"
       
"log"
       
"os"
       
"time"

       
"github.com/golang/protobuf/proto"
        v1
"google.golang.org/genproto/googleapis/maps/routes/v1"
        v1alpha
"google.golang.org/genproto/googleapis/maps/routes/v1alpha"
       
"google.golang.org/genproto/googleapis/type/latlng"
       
"google.golang.org/grpc"
       
"google.golang.org/grpc/credentials"
       
"google.golang.org/grpc/metadata"
)

const (
        serverAddr
= "routespreferred.googleapis.com:443"
       
// Note that setting the field mask to * is OK for testing, but discouraged in
       
// production.
       
// For example, for ComputeRoutes, set the field mask to
       
// "routes.distanceMeters,routes.duration,routes.polyline.encodedPolyline"
       
// in order to get the route distances, durations, and encoded polylines.
        fieldMask
= "*"
)

func createWaypoint
(lat float64, lng float64) *v1.Waypoint {
       
return &v1.Waypoint{LocationType: &v1.Waypoint_Location{
               
Location: &v1.Location{
                       
LatLng: &latlng.LatLng{Latitude: lat, Longitude: lng},
               
},
       
}}
}

func callComputeCustomRoutes
(client v1alpha.RoutesAlphaClient, ctx *context.Context) {
        request
:= v1.ComputeCustomRoutesRequest{
               
Origin:      createWaypoint(37.420761, -122.081356),
               
Destination: createWaypoint(37.420999, -122.086894),
               
RouteObjective: &v1.RouteObjective{
                       
Objective: &v1.RouteObjective_RateCard_{
                               
RateCard: &v1.RouteObjective_RateCard{
                                       
CostPerMinute: &v1.RouteObjective_RateCard_MonetaryCost{Value: 1.1},
                               
},
                       
},
               
},
               
TravelMode:        v1.RouteTravelMode_DRIVE,
               
RoutingPreference: v1.RoutingPreference_TRAFFIC_AWARE,
               
Units:             v1.Units_METRIC,
               
LanguageCode:      "en-us",
               
RouteModifiers: &v1.RouteModifiers{
                       
AvoidTolls:    false,
                       
AvoidHighways: true,
                       
AvoidFerries:  true,
               
},
               
PolylineQuality: v1.PolylineQuality_OVERVIEW,
       
}
        marshaler
:= proto.TextMarshaler{}
        log
.Printf("Sending request: \n%s", marshaler.Text(&request))
        result
, err := client.ComputeCustomRoutes(*ctx, &request)

       
if err != nil {
                log
.Fatalf("Failed to call ComputeCustomRoutes: %v", err)
       
}
        log
.Printf("Result: %s", marshaler.Text(result))
}

func main
() {
        config
:= tls.Config{}
        conn
, err := grpc.Dial(serverAddr,
                grpc
.WithTransportCredentials(credentials.NewTLS(&config)))
       
if err != nil {
                log
.Fatalf("Failed to connect: %v", err)
       
}
        defer conn
.Close()
        client
:= v1alpha.NewRoutesAlphaClient(conn)
        ctx
, cancel := context.WithTimeout(context.Background(), 2*time.Second)
        ctx
= metadata.AppendToOutgoingContext(ctx, "X-Goog-Api-Key", os.Getenv("GOOGLE_MAPS_API_KEY"))
        ctx
= metadata.AppendToOutgoingContext(ctx, "X-Goog-Fieldmask", fieldMask)
        defer cancel
()

        callComputeCustomRoutes
(client, &ctx)
}

 

计算过路费示例

以下示例使用 computeCustomRoutes 方法返回路线的过路费信息,并附带使用过路费卡时估算的价格。

此功能可通过请求中指定的 routes.travelAdvisory.tollInfo 字段掩码启用。通行卡是在 route_modifiers 字段中指定的。返回的过路费价格基于指定卡券使用的价格。如果指定了多个卡券,系统会返回价格最低的卡券。

请求:

curl -X POST -d '{
  "origin":{
    "location":{
      "latLng":{
        "latitude":47.7020056,
        "longitude":-122.3479236
      }
    }
  },
  "destination":{
    "location":{
      "latLng":{
        "latitude":47.6192234,
        "longitude": -122.1676792
      }
    }
  },
  "travelMode":"DRIVE",
  "routingPreference": "TRAFFIC_AWARE_OPTIMAL",
  "routeModifiers":{
    "vehicleInfo":{
      "emissionType": "GASOLINE"
    },
    "tollPasses": [
      "US_MA_EZPASSMA",
      "US_WA_GOOD_TO_GO"
    ]
  },
  "routeObjective":{
    "rateCard":{
      "costPerMinute":{
        "value":2
      },
      "costPerKm":{
        "value": 1
      },
      "includeTolls": true
    }
  }
}'
\
-H 'Content-Type: application/json' \
-H 'X-Goog-Api-Key: <YOUR_API_KEY>' \
-H 'X-Goog-FieldMask: routes.route.duration,routes.route.distanceMeters,routes.route.travelAdvisory.tollInfo,routes.route.legs.travelAdvisory.tollInfo,fallbackInfo' \
'https://routespreferred.googleapis.com/v1alpha:computeCustomRoutes'

回答:

{
 
"routes": [
   
{
     
"route": {
       
"legs": [
         
{
           
"travelAdvisory": {
             
"tollInfo": {
           
"estimatedPrice": [
             
{
               
"currencyCode": "USD",
               
"units": "2",
               
"nanos": 700000000
             
}
           
]
         
}
       
}
     
}
   
],
   
"distanceMeters": 22496,
   
"duration": "1391s",
   
"travelAdvisory": {
     
"tollInfo": {
       
"estimatedPrice": [
         
{
           
"currencyCode": "USD",
           
"units": "2",
           
"nanos": 700000000
         
}
       
]
     
}
   
}
 
]
}

以下示例使用 computeCustomRoutes 方法返回没有价格估算的路线的过路费信息。

您还可以使用请求中指定的 routes.travelAdvisory.tollInfo 字段掩码启用此功能。如果在请求时无法估算过路费,则这是 API 的预期行为。通常,如果响应中存在 tollInfo 字段,则表示相应路线有收费。

如果您在 routeObjective 中指定了 include_tolls,但 Google 没有相应路线的过路费价格信息,则响应中会包含回退 routeObjective FALLBACK_RATECARD_WITHOUT_TOLL_PRICE_DATA。

请求:

curl -X POST -d '{
  "origin":{
    "location":{
      "latLng":{
        "latitude":39.56227274,
        "longitude":15.12008516
      }
    }
  },
  "destination":{
    "location":{
      "latLng":{
        "latitude":39.56205718,
        "longitude": 15.12250773
      }
    }
  },
  "travelMode":"DRIVE",
  "routingPreference": "TRAFFIC_AWARE",
  "routeObjective":{
    "rateCard":{
      "costPerMinute":{
        "value":1
      },
      "costPerKm":{
        "value": 1
      },
      "includeTolls": true
    }
  }
}'
\
-H 'Content-Type: application/json' \
-H 'X-Goog-Api-Key: <YOUR_API_KEY>' \
-H 'X-Goog-FieldMask: routes.route.duration,routes.route.distanceMeters,routes.route.travelAdvisory.tollInfo,routes.route.legs.travelAdvisory.tollInfo.estimatedPrice,fallbackInfo' \
'https://routespreferred.googleapis.com/v1alpha:computeCustomRoutes'

回答:

{
 
"routes": [
   
{
     
"route": {
       
"legs": [
         
{
           
"travelAdvisory": {
             
"tollInfo": {}
           
}
         
}
       
],
       
"distanceMeters": 101,
       
"duration": "10s",
       
"travelAdvisory": {
         
"tollInfo": {}
       
}
     
}
   
}
 
],
 
"fallbackInfo": {
   
"routeObjective": "FALLBACK_RATECARD_WITHOUT_TOLL_PRICE_DATA"
 
}
}