Realiza tu primera solicitud de Route Optimization… con perros

Desarrolladores del Espacio Económico Europeo (EEE)

En este documento, se muestra cómo realizar tu primera solicitud a la API de Route Optimization con una situación de caso de uso real.

Para simplificar, en el ejemplo se usan HTTP y JSON para demostrar la API de REST. Sin embargo, para tu entorno de producción, la recomendación general es usar gRPC por sus beneficios de rendimiento. Sin embargo, gRPC requiere cierta instalación. Para obtener más información, consulta las bibliotecas cliente de la API de Route Optimization.

Situación

Un mapa de San Francisco con pines para la Torre Coit, el parque Mission Dolores y el parque South Sunset Playground

Tienes una guardería para perros en San Francisco que funciona de 7 a.m. a 7 p.m. Esta mañana, quieres recoger a tres perros de diferentes ubicaciones de la ciudad y llevarlos a tu guardería.

El boyero de Berna y el chihuahua son clientes habituales que reservaron sus citas la semana pasada. El pastor alemán es una solicitud nueva de último momento. Quieres hacerle un lugar al pastor alemán si es posible, pero no a expensas de tus clientes habituales.

Tienes una camioneta para el trabajo y le pagas al conductor $27 por hora. El conductor y la camioneta comienzan el día en tu guardería a las 7:00 a.m. y deben regresar de las recogidas de la mañana antes del mediodía para tomar un descanso para almorzar.

Hoy es 13 de febrero de 2024. Todas las horas de esta situación corresponden a la hora local de San Francisco, que es la hora estándar del Pacífico (UTC-8) en febrero. El conductor tiene las siguientes tareas:

  • Recoge al boyero de Berna cerca de la Torre Coit. El propietario solicitó un intervalo de retiro acotado entre las 8:00 a.m. y las 8:20 a.m.
  • Recoge al chihuahua en el South Sunset Playground Park. El propietario ofreció un horario de retiro más flexible, entre las 7:30 a.m. y las 9:30 a.m.
  • Recoge al pastor alemán en Land's End. El propietario también solicitó un período de retiro estricto entre las 8:00 a.m. y las 8:20 a.m.
  • Deja a los perros en la guardería del parque Mission Dolores. La guardería requiere que se deje a los niños entre las 9:30 a.m. y las 11:30 a.m.

Cada visita de retiro y entrega tarda 5 minutos en cargar o descargar al perro.

Debido a que Land's End está lejos de Coit Tower y sus ventanas de retiro entran en conflicto, el conductor no puede realizar los tres retiros. El optimizador debe elegir qué perro omitir para minimizar el costo total (salarios de los conductores y cualquier penalización por omisión).

Antes de comenzar

Para ejecutar el código de esta situación de ejemplo, primero debes completar las instrucciones que se indican en Configura la API de Route Optimization.

1. Elige tu enfoque de optimización de rutas

La API de Route Optimization tiene varios métodos para que elijas según la complejidad de tu problema de optimización.

Debido a que esta situación de guardería para perros es una solicitud pequeña y directa, usa un método de bloqueo, como optimizeTours, que entrega resultados con rapidez para solicitudes pequeñas. Para obtener más información sobre los endpoints de la API de Route Optimization, consulta Elige un endpoint.

Usa la siguiente URL para realizar una solicitud POST HTTP al método optimizeTours:

https://routeoptimization.googleapis.com/v1/projects/PROJECT_OR_ID:optimizeTours

También debes configurar los parámetros de configuración de tiempo de espera y fecha límite para que sean cortos y, así, reducir cualquier tiempo de espera innecesario. Para esta situación de guardería de perros, el optimizador no necesita mucho tiempo para responder a tu solicitud, por lo que debes usar la siguiente configuración:

  • Establece el parámetro timeout en 2 segundos.
  • Deja la configuración del plazo en el valor predeterminado, que es de 60 segundos para las solicitudes de REST.

2. Crea el cuerpo del mensaje de solicitud

Después de elegir el método optimizeTours de bloqueo y definir la configuración de tiempo de espera y plazo, el siguiente paso es construir el cuerpo del mensaje de solicitud.

En este caso, la solicitud es un mensaje OptimizeToursRequest codificado como JSON en la API de REST.

Para construir el mensaje de solicitud, sigue estos pasos:

  1. Comienza con la estructura básica de la solicitud, que es la siguiente:

    {
      "timeout": ...,
      "model": {
        "shipments": [...],
        "vehicles": [...],
        "globalStartTime": "...",
        "globalEndTime": "..."
      }
    }
    

    Para obtener más información sobre la estructura, consulta la guía de conceptos clave de la estructura base (ShipmentModel, Shipment y Vehicle).

  2. Define los envíos. En el campo shipments, agrega un mensaje Shipment para cada perro que se deba recoger y dejar por la mañana. Aquí es donde defines la ubicación y los horarios de retiro preferidos de cada propietario de perro, y la ubicación y los horarios de la guardería para dejar a los perros.

    1. Para cada perro, crea un VisitRequest para las recogidas y otro para las entregas, que, en este caso, se denomina entrega en la guardería.

      • En las recogidas, establece el arrivalWaypoint en la ubicación de recogida del perro (Coit Tower para el boyero de Berna, South Sunset Playground Park para el chihuahua o Land's End para el pastor alemán). Establece el timeWindows en la hora de partida solicitada por el propietario (de 8:00 a.m. a 8:20 a.m. para el boyero de Berna y el pastor alemán, y de 7:30 a.m. a 9:30 a.m. para el chihuahua).

      • En las entregas, establece el arrivalWaypoint en la guardería y el timeWindows para la hora de llegada requerida (de 9:30 a.m. a 11:30 a.m.).

      • Para todas las recogidas y entregas, establece el duration en 5 minutos (300s) para tener en cuenta la carga y descarga de los perros.

      Para obtener más información sobre las ventanas de tiempo, consulta Ventanas de tiempo.

    2. Para priorizar a los clientes habituales, establece el penaltyCost en 1000 para el boyero de Berna y el chihuahua, y en 100 para el pastor alemán. Con los costos de penalización establecidos, el optimizador puede omitir cualquiera de los perros, pero considera omitir primero al pastor alemán (que tiene una penalización más baja) si las restricciones imposibilitan realizar todas las recogidas.

    3. Puedes usar el campo label para agregar un identificador para cada envío, como "Boyero de Berna", "Chihuahua" y "Pastor alemán". Esto puede ayudarte a identificar los envíos en la respuesta.

    Para obtener más información sobre cómo definir los envíos, consulta Envío.

  3. Define los vehículos. En el campo vehicles, agrega un mensaje Vehicle para tu camioneta con la guardería como punto de partida y de llegada, el costo del salario del conductor y el horario de atención de la camioneta.

    1. Establece startWaypoint y endWaypoint para la camioneta en las ubicaciones de inicio y finalización del día, que es la guardería cerca de Mission Dolores Park.

    2. Para minimizar los costos de operación, debes definir las restricciones de costos de tu empresa. Establece el parámetro de costo costPerHour en 27, que es el importe que le pagas al conductor por conducir la camioneta de la guardería para perros. Para obtener más información sobre los parámetros de costo, consulta Modelo de costos.

    3. Para asegurarte de que el optimizador cree una ruta dentro del horario de atención de la camioneta, define un período de operación para el vehículo. Esta ventana establece las restricciones de hora de inicio y finalización de la ruta. Si defines solo una mitad de cada ventana de tiempo, le darás flexibilidad al optimizador para comenzar la ruta más tarde o finalizarla antes:

      • Establecer startTime en startTimeWindows en las 7 a.m. significa que el conductor puede comenzar su turno a partir de las 7 a.m. También puede comenzar más tarde si no hay retiros temprano por la mañana.

      • Si configuras endTime en endTimeWindows para el mediodía, el conductor debe finalizar su turno antes del mediodía. También pueden finalizar su turno en cuanto completen la última entrega.

      Omitir la otra mitad de las ventanas minimiza los tiempos de espera y desvío del conductor. Para obtener más información sobre las ventanas de tiempo, consulta Ventanas de tiempo.

    Para obtener más información sobre cómo definir vehículos, consulta Vehículo.

  4. Establece un período global. La ventana de tiempo global representa el período en el que la camioneta puede realizar retiros y entregas para tu guardería durante el día. En esta situación, establece globalStartTime en las 7 a.m. y globalEndTime en las 7 p.m. para el 13 de febrero de 2024, que representan el horario de atención de la guardería para perros.

3. Envía la solicitud

A continuación, se muestra una solicitud curl simple basada en la situación de la guardería de perros y usa el método optimizeTours de bloqueo.

Antes de enviar la solicitud, reemplaza PROJECT_NUMBER_OR_ID en el código de muestra por tu ID del proyecto de Google Cloud.

curl -X POST 'https://routeoptimization.googleapis.com/v1/projects/PROJECT_NUMBER_OR_ID:optimizeTours' \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
--data @- << EOM
{
  "timeout": "2s",
  "model": {
    "shipments": [
      {
        "pickups": [
          {
            "arrivalWaypoint": {
              "location": {
                "latLng": {
                  "latitude": 37.802395,
                  "longitude": -122.405822
                }
              }
            },
            "timeWindows": [
              {
                "startTime": "2024-02-13T08:00:00-08:00",
                "endTime": "2024-02-13T08:20:00-08:00"
              }
            ],
            "duration": "300s"
          }
        ],
        "deliveries": [
          {
            "arrivalWaypoint": {
              "location": {
                "latLng": {
                  "latitude": 37.759719,
                  "longitude": -122.42798
                }
              }
            },
            "timeWindows": [
              {
                "startTime": "2024-02-13T09:30:00-08:00",
                "endTime": "2024-02-13T11:30:00-08:00"
              }
            ],
            "duration": "300s"
          }
        ],
        "label": "Bernese mountain dog",
        "penaltyCost": 1000
      },
      {
        "pickups": [
          {
            "arrivalWaypoint": {
              "location": {
                "latLng": {
                  "latitude": 37.738067,
                  "longitude": -122.498593
                }
              }
            },
            "timeWindows": [
              {
                "startTime": "2024-02-13T07:30:00-08:00",
                "endTime": "2024-02-13T09:30:00-08:00"
              }
            ],
            "duration": "300s"
          }
        ],
        "deliveries": [
          {
            "arrivalWaypoint": {
              "location": {
                "latLng": {
                  "latitude": 37.759719,
                  "longitude": -122.42798
                }
              }
            },
            "timeWindows": [
              {
                "startTime": "2024-02-13T09:30:00-08:00",
                "endTime": "2024-02-13T11:30:00-08:00"
              }
            ],
            "duration": "300s"
          }
        ],
        "label": "Chihuahua",
        "penaltyCost": 1000
      },
      {
        "pickups": [
          {
            "arrivalWaypoint": {
              "location": {
                "latLng": {
                  "latitude": 37.78018,
                  "longitude": -122.51194
                }
              }
            },
            "timeWindows": [
              {
                "startTime": "2024-02-13T08:00:00-08:00",
                "endTime": "2024-02-13T08:20:00-08:00"
              }
            ],
            "duration": "300s"
          }
        ],
        "deliveries": [
          {
            "arrivalWaypoint": {
              "location": {
                "latLng": {
                  "latitude": 37.759719,
                  "longitude": -122.42798
                }
              }
            },
            "timeWindows": [
              {
                "startTime": "2024-02-13T09:30:00-08:00",
                "endTime": "2024-02-13T11:30:00-08:00"
              }
            ],
            "duration": "300s"
          }
        ],
        "label": "German shepherd",
        "penaltyCost": 100
      }
    ],
    "vehicles": [
      {
        "startWaypoint": {
          "location": {
            "latLng": {
              "latitude": 37.759719,
              "longitude": -122.42798
            }
          }
        },
        "endWaypoint": {
          "location": {
            "latLng": {
              "latitude": 37.759719,
              "longitude": -122.42798
            }
          }
        },
        "costPerHour": 27,
        "startTimeWindows": [
          {
            "startTime": "2024-02-13T07:00:00-08:00"
          }
        ],
        "endTimeWindows": [
          {
            "endTime": "2024-02-13T12:00:00-08:00"
          }
        ]
      }
    ],
    "globalStartTime": "2024-02-13T07:00:00-08:00",
    "globalEndTime": "2024-02-13T19:00:00-08:00"
  }
}
EOM

Parámetros de solicitud que se usan en la solicitud

En la siguiente tabla, se describen los parámetros de solicitud que se usan en el cuerpo de la solicitud del caso de ejemplo. Puedes filtrar el contenido por elemento superior o por búsqueda de texto.

Padres Parámetro Tipo de propiedad Descripción
OptimizeToursRequest model objeto (ShipmentModel) Esta es la parte central de tu solicitud. Es un objeto único en el que defines todo el problema, incluidos todos los perros que debes recoger y dejar (shipments) y la camioneta de tu flota (vehicles). Piensa en él como el plano completo del problema que necesitas optimizar.
timeout Duración Este parámetro especifica el tiempo máximo que el servidor trabaja en una solicitud antes de devolver una respuesta. Usa este parámetro para acortar el tiempo de espera. Para solicitudes pequeñas y rápidas, como en este caso de la guardería de perros, establece este valor en 2s.
ShipmentModel shipments[] array de objetos (Shipment) Este es un array de objetos en el que cada objeto representa un perro que se debe recoger o dejar.
vehicles[] array de objetos (Vehicle) Este es un array de objetos en el que cada objeto define un vehículo de tu flota. Aquí es donde describes tus recursos, como la camioneta que realiza las recogidas y entregas. Debes definir al menos un vehículo para obtener una ruta optimizada.
globalStartTime Marca de tiempo Esta es la hora más temprana posible para que ocurra cualquier evento en todo tu modelo. Este parámetro reduce el problema de optimización en el tiempo, lo que es fundamental para realizar cálculos precisos de tráfico y rutas. En este caso de guardería para perros, establece este valor en la hora más temprana en la que el conductor puede operar la camioneta durante el día, que es a las 7 a.m. del 13 de febrero de 2024.
globalEndTime Marca de tiempo Esta es la hora más tardía posible para que ocurra cualquier evento en todo el modelo. En este caso de guardería para perros, configúrala para cuando se espera que la camioneta finalice su operación, que es a las 7 p.m. del 13 de febrero de 2024.
Shipment pickups[] array de objetos (VisitRequest) Esta es una lista de todas las opciones de retiro posibles para el envío. El optimizador elige el mejor para resolver tu problema. Para esta situación de guardería de perros, enumera las ubicaciones de retiro y los períodos que cada propietario proporcionó para cada perro.
deliveries[] array de objetos (VisitRequest) Esta es una lista de todas las opciones de entrega posibles para el envío. El optimizador elige el mejor para resolver tu problema. En este caso de guardería para perros, indica la ubicación de la guardería y el período en el que el conductor debe regresar para almorzar para cada perro.
label string Es un identificador de un envío específico de tu solicitud. Puedes especificar etiquetas en tu solicitud para que sea más fácil leer la respuesta. Para este caso de guardería de perros, usa una cadena descriptiva como "Chihuahua", "Boyero de Berna" o el nombre del perro para que la solución coincida con tu entrada cuando recibas la respuesta de la API.
penaltyCost doble Este es el costo de penalización en el que se incurre si el optimizador omite este envío. De forma predeterminada, los envíos son obligatorios: el optimizador prioriza minimizar los envíos obligatorios omitidos y los omite solo cuando no hay otra opción. Establecer un costo de penalización permite que el optimizador omita un envío si no es factible o es demasiado costoso realizarlo, y te permite sopesar las prioridades entre los envíos. En esta situación, estableces un costo de penalización más alto (1000) para tus clientes habituales (boyero de Berna y chihuahua) y un costo de penalización más bajo (100) para la solicitud de último momento del pastor alemán. Esto le indica al optimizador que priorice a los clientes habituales, por lo que considera omitir al pastor alemán primero cuando no puede realizar todas las recogidas.
VisitRequest arrivalWaypoint objeto (Waypoint) Esta es la ubicación de una visita específica en la ruta. Puedes definirla con coordenadas de latitud y longitud, un ID de lugar o un rumbo. En este caso de la guardería para perros, establece este valor en la ubicación que proporcionó el propietario para pickups y en la dirección de la guardería para deliveries.
timeWindows[] array de objetos (TimeWindow) Es un array de objetos que definen las restricciones de tiempo para un retiro o una entrega. En este caso, usa este parámetro para definir el período de retiro de cada perro y el período aceptable para dejarlos en la guardería.
duration Duración Este parámetro especifica la duración de la visita (p.ej., el tiempo de carga o descarga). En esta situación, estableces un margen de 5 minutos (300s) para todas las recogidas y entregas, de modo que se tenga en cuenta el tiempo que tarda el conductor en subir y bajar a los perros.
Vehicle startWaypoint objeto (Waypoint) Es la ubicación de partida de la ruta del vehículo, definida con coordenadas de latitud y longitud, o un ID de lugar. Este parámetro le indica al optimizador dónde debe comenzar la ruta el vehículo. Si no defines este punto de referencia, el optimizador elegirá uno de los puntos de retiro o entrega como ubicación de partida. En este caso de guardería para perros, como el conductor comienza el día en la guardería, usa las coordenadas del parque Mission Dolores.
endWaypoint objeto (Waypoint) Es el destino final de la ruta del vehículo, definido con coordenadas de latitud y longitud, o un ID de lugar. Este parámetro le indica al optimizador dónde debe finalizar la ruta el vehículo. Si no defines este punto de referencia, el optimizador elegirá una de las recogidas o entregas como el final de la ruta. En este caso de la guardería para perros, como el conductor debe terminar el día en la guardería, usa las coordenadas de Mission Dolores Park.
costPerHour número Es el costo que se genera por cada hora que se usa un vehículo, sin importar si está en movimiento o detenido. Para este caso de guardería de perros, usa esto para modelar el salario por hora de un conductor.
startTimeWindows[] array de objetos (TimeWindow) Este es el período aceptable para que el conductor comience su turno. Para este caso de guardería de perros, define startTime como las 7 a.m., pero omite endTime. Esto permite que el optimizador retrase el inicio del turno si la primera recolección es más tarde en la mañana. Ten en cuenta que, incluso si no proporcionas un endTime para startTimeWindows, la hora de inicio está limitada de forma implícita por el endTimeWindows. El vehículo debe comenzar la ruta antes de que esta finalice.
endTimeWindows[] array de objetos (TimeWindow) Este es el período aceptable para que el conductor finalice la ruta. Para este caso de uso de guardería de perros, define el endTime como el mediodía, pero omite el startTime. Esto permite que el conductor regrese a la guardería inmediatamente después de la última parada.

Siguiente

Interpretar la respuesta