Skip to main content
API de otimizacao de rotas: reduza os custos de entrega em 30
Tutorials

API de otimizacao de rotas: reduza os custos de entrega em 30

Use a API de roteamento da MapAtlas para otimizar rotas de entrega com multiplas paradas, aplicar janelas de tempo

Brent van der Heiden11 min read
#route optimization#delivery route#routing api#last mile delivery#multi-stop route#logistics api

A entrega na milha final é a parte mais cara de qualquer cadeia de suprimentos. Os benchmarks da indústria consistentemente colocam os custos da milha final em 53% do custo total de envio. Dentro disso, a variável controlável mais importante é a eficiência da rota. Um motorista completando 15 paradas na ordem errada pode dirigir 40% a mais de quilómetros do que o necessário, queimando combustível, desgastando o veículo e perdendo as janelas de tempo de entrega que desencadeiam taxas de reentrega.

A otimização de rotas não é mais um problema difícil de resolver em código. O que costumava exigir software de logística especializado caro agora é uma chamada de API. Este tutorial constrói um otimizador de rotas com múltiplas paradas usando a API de Roteamento MapAtlas: um script Python que envia uma lista de paradas de entrega, obtém uma sequência otimizada com distância total e tempo, aplica restrições de janelas de tempo e lida com restrições de Zonas de Baixa Emissão da UE para entregas urbanas. Um snippet de JavaScript então desenha o resultado em um mapa.

A implementação em Python tem menos de 55 linhas. A exibição do mapa em JavaScript são 30 linhas adicionais.

O Problema do Custo da Milha Final

Para entender o que a otimização realmente economiza, calcule os números para um cenário de entrega realista:

  • Frota: 10 vans
  • Paradas por van por dia: 18
  • Distância média atual: 210 km/van/dia
  • Custo de combustível: €0,38/km (diesel, média UE)
  • Custo do motorista: €22/hora
  • Tempo médio de rota atual: 7,5 horas/dia

Custo diário atual por van: (210 × €0,38) + (7,5 × €22) = €79,80 + €165 = €244,80/van/dia

Uma redução de 30% na distância (alcançável com boa otimização em uma rede urbana densa) e uma economia de 20% no tempo produz:

  • Distância otimizada: 147 km → custo de combustível: €55,86
  • Tempo otimizado: 6 horas → custo do motorista: €132
  • Custo diário otimizado por van: €187,86/van/dia

Economia por van por dia: €56,94. Para 10 vans em 250 dias úteis: €142.350/ano, com uma integração de API.

Os benchmarks acima refletem números reais publicados em estudos de logística de milha final. Seus números específicos variarão por geografia, tipo de veículo e densidade de paradas. Áreas urbanas densas veem os maiores ganhos porque as rotas sequenciais ingênuas desperdiçam a maior distância em backtracking desnecessário.

Rotas Ingênuas vs Otimizadas: Uma Comparação Visual

A diferença entre uma rota ingênua (sequencial) e uma otimizada é marcante em um mapa.

O roteamento ingênuo ocorre quando você alimenta paradas na ordem em que foram inseridas, o primeiro cliente que fez um pedido é o primeiro na rota, independentemente da geografia. Em uma cidade como Amsterdã ou Berlim, isso cria o problema da "rota de espaguete": seu motorista constantemente cruzando seu próprio caminho.

A otimização resolve o Problema do Caixeiro Viajante (TSP) para seu conjunto de paradas. Para 15 a 20 paradas, isso é computacionalmente tratável em milissegundos. Para frotas maiores com centenas de paradas, solucionadores de problema de roteamento de veículos (VRP) lidam com as restrições adicionais de múltiplos veículos e limites de capacidade.

Passo 1: Estruture Seus Dados de Entrega

Cada parada precisa de uma localização e, para entregas com janela de tempo, um time_window especificando quando a entrega é aceitável.

import requests
import json

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.mapatlas.eu/v1"

# Depot (start and end point)
depot = {
    "lat": 52.3402,
    "lng": 4.8952,
    "name": "Warehouse - Sloterdijk"
}

# Delivery stops with optional time windows
stops = [
    { "lat": 52.3726, "lng": 4.8971, "name": "Albert Heijn Jordaan",
      "time_window": { "start": "09:00", "end": "12:00" } },
    { "lat": 52.3601, "lng": 4.9123, "name": "Café De Jaren",
      "time_window": { "start": "08:00", "end": "11:00" } },
    { "lat": 52.3780, "lng": 4.8801, "name": "Westergasfabriek Events",
      "time_window": { "start": "10:00", "end": "14:00" } },
    { "lat": 52.3545, "lng": 4.9041, "name": "Hotel V Nesplein",
      "time_window": None },
    { "lat": 52.3620, "lng": 4.8820, "name": "Vondelpark Paviljoen",
      "time_window": { "start": "07:00", "end": "10:00" } }
]

Passo 2: Chame o Endpoint de Otimização de Rota

Envie POST o depósito e a lista de paradas para o endpoint de roteamento otimizado. A API retorna as paradas na ordem de visita mais eficiente, juntamente com a distância total da rota e duração.

def optimise_route(depot, stops, vehicle_profile="van-euro6"):
    """
    Request an optimised multi-stop route from the MapAtlas Routing API.
    vehicle_profile options: van-euro6, van-diesel-euro5, electric-van, bike
    """
    waypoints = [
        {
            "lat": s["lat"],
            "lng": s["lng"],
            "name": s["name"],
            **({"time_window": s["time_window"]} if s.get("time_window") else {})
        }
        for s in stops
    ]

    payload = {
        "origin": { "lat": depot["lat"], "lng": depot["lng"] },
        "destination": { "lat": depot["lat"], "lng": depot["lng"] },  # return to depot
        "waypoints": waypoints,
        "optimise": True,
        "vehicle_profile": vehicle_profile,
        "avoid_low_emission_zones": True  # auto-avoids LEZs for non-compliant profiles
    }

    response = requests.post(
        f"{BASE_URL}/routing/optimise",
        json=payload,
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json"
        }
    )
    response.raise_for_status()
    return response.json()

result = optimise_route(depot, stops)

Passo 3: Analisar e Exibir a Rota Otimizada

A resposta da API inclui as paradas em ordem otimizada, ETAs cumulativas para cada parada, distância total e duração total.

def display_route_summary(result):
    route = result["route"]
    print(f"\n--- Optimised Route Summary ---")
    print(f"Total distance : {route['total_distance_km']:.1f} km")
    print(f"Total duration : {route['total_duration_min']:.0f} min")
    print(f"Stops          : {len(route['waypoints'])}\n")

    print(f"  START  {depot['name']}")
    for i, stop in enumerate(route["waypoints"], 1):
        eta     = stop["eta"]
        tw      = stop.get("time_window")
        on_time = "(on time)" if tw and tw["start"] <= eta <= tw["end"] else ""
        print(f"  {i:>2}.   {stop['name']:<35} ETA {eta}  {on_time}")
    print(f"  END    {depot['name']}")

    print(f"\nEstimated fuel saving vs sequential: "
          f"{result.get('saving_vs_naive_km', 0):.1f} km "
          f"({result.get('saving_pct', 0):.0f}%)")

display_route_summary(result)

Exemplo de saída para as cinco paradas acima:

--- Resumo da Rota Otimizada ---
Distância total  : 38.4 km
Duração total    : 94 min
Paradas          : 5

  INÍCIO  Warehouse - Sloterdijk
   1.   Vondelpark Paviljoen               ETA 07:48  (no horário)
   2.   Café De Jaren                      ETA 08:31  (no horário)
   3.   Albert Heijn Jordaan               ETA 09:15  (no horário)
   4.   Hotel V Nesplein                   ETA 10:02
   5.   Westergasfabriek Events            ETA 10:44  (no horário)
  FIM    Warehouse - Sloterdijk

Economia de combustível estimada vs sequencial: 14.2 km (27%)

Passo 4: Manipulação de Zonas de Baixa Emissão da UE

A zona ZTL de Amsterdã, o sistema Crit'Air de Paris e a Umweltzone de Berlim restringem certos tipos de veículos de áreas centrais em horários específicos. Uma rota que parece eficiente apenas em distância pode ser inválida para seu veículo.

O parâmetro avoid_low_emission_zones: true combinado com o vehicle_profile roteia automaticamente em torno de zonas restritas para veículos não conformes. Para veículos elétricos e Euro 6, as LEZs são transitáveis e o parâmetro não tem efeito.

# Exemplo: van diesel Euro 5, será roteada ao redor do ZTL de Amsterdã
result_euro5 = optimise_route(depot, stops, vehicle_profile="van-diesel-euro5")

# Exemplo: van elétrica, restrições LEZ não se aplicam
result_electric = optimise_route(depot, stops, vehicle_profile="electric-van")

print(f"Distância de rota Euro 5  : {result_euro5['route']['total_distance_km']:.1f} km")
print(f"Distância de rota elétrica: {result_electric['route']['total_distance_km']:.1f} km")
# A rota elétrica será tipicamente mais curta, pois pode usar estradas com restrição LEZ

Para operações de logística planejando uma transição de diesel para elétrico, comparar essas duas saídas por rota fornece uma quantificação direta da melhoria de autonomia disponível com a eletrificação.

Passo 5: Exiba a Rota Otimizada em um Mapa

Pegue a geometria da rota da resposta da API e processe-a como uma camada de linha em JavaScript.

import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';

// routeResult is the parsed API JSON response passed to the frontend
function renderOptimisedRoute(map, routeResult) {
  const { waypoints, geometry, total_distance_km, total_duration_min } = routeResult.route;

  map.on('load', () => {
    // Route line
    map.addSource('optimised-route', { type: 'geojson', data: { type: 'Feature', geometry } });
    map.addLayer({
      id: 'route-line',
      type: 'line',
      source: 'optimised-route',
      layout: { 'line-join': 'round', 'line-cap': 'round' },
      paint: { 'line-color': '#2563EB', 'line-width': 4 }
    });

    // Stop markers with sequence numbers
    waypoints.forEach((stop, i) => {
      const el = document.createElement('div');
      el.textContent = i + 1;
      el.style.cssText = `
        width:28px;height:28px;border-radius:50%;background:#2563EB;color:#fff;
        display:flex;align-items:center;justify-content:center;font-weight:700;
        font-size:13px;border:2px solid #fff;box-shadow:0 2px 6px rgba(0,0,0,0.3)
      `;

      new mapmetricsgl.Marker({ element: el })
        .setLngLat([stop.lng, stop.lat])
        .setPopup(
          new mapmetricsgl.Popup().setHTML(`
            <strong>${i + 1}. ${stop.name}</strong>
            <p>ETA: ${stop.eta}</p>
          `)
        )
        .addTo(map);
    });

    // Fit map to route bounds
    const coords = geometry.coordinates;
    const bounds = coords.reduce(
      (b, c) => b.extend(c),
      new mapmetricsgl.LngLatBounds(coords[0], coords[0])
    );
    map.fitBounds(bounds, { padding: 48 });

    // Summary panel
    document.getElementById('route-summary').innerHTML = `
      <strong>${total_distance_km.toFixed(1)} km</strong> ·
      <strong>${total_duration_min.toFixed(0)} min</strong> ·
      ${waypoints.length} stops
    `;
  });
}

const map = new mapmetricsgl.Map({
  container: 'route-map',
  style: 'https://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY',
  center: [4.9041, 52.3676],
  zoom: 12
});

renderOptimisedRoute(map, routeResult);

Calculando Suas Economias Reais

Depois de ter a resposta da API em mãos, o cálculo da economia é direto. O campo saving_vs_naive_km na resposta fornece a distância economizada diretamente. A partir daí, derive a economia de custo:

def calculate_savings(result, fuel_cost_per_km=0.38, driver_cost_per_hour=22.0,
                       days_per_year=250, fleet_size=10):
    saving_km    = result.get("saving_vs_naive_km", 0)
    saving_hours = saving_km / 50  # assume 50 km/h average

    daily_fuel_saving   = saving_km * fuel_cost_per_km
    daily_driver_saving = saving_hours * driver_cost_per_hour
    daily_total         = daily_fuel_saving + daily_driver_saving

    annual_fleet_saving = daily_total * days_per_year * fleet_size

    print(f"Distance saved per route : {saving_km:.1f} km")
    print(f"Time saved per route     : {saving_hours * 60:.0f} min")
    print(f"Daily saving (1 vehicle) : €{daily_total:.2f}")
    print(f"Annual saving ({fleet_size} vehicles): €{annual_fleet_saving:,.0f}")

calculate_savings(result)

Otimização de Janela de Tempo

Entregar em uma padaria às 06:00 e em um restaurante às 14:00 enquanto minimiza a distância total da rota é um problema de otimização restrita. A API lida com isso automaticamente, você só precisa fornecer as janelas:

# Paradas sensíveis ao tempo, a API agendará estas dentro de suas janelas
stops_with_windows = [
    { "lat": 52.3726, "lng": 4.8971, "name": "Padaria",
      "time_window": { "start": "05:30", "end": "07:00" } },
    { "lat": 52.3620, "lng": 4.8820, "name": "Café",
      "time_window": { "start": "07:00", "end": "09:00" } },
    { "lat": 52.3545, "lng": 4.9041, "name": "Restaurante",
      "time_window": { "start": "13:00", "end": "15:00" } }
]

Se alguma restrição de janela de tempo não puder ser satisfeita dado o horário de partida do depósito e modelo de tráfego atual, a API retorna um array constraint_violations listando quais paradas não puderam ser alcançadas no horário. Seu software de despacho pode então alertar o motorista ou sugerir uma partida anterior.

O Que Construir Nesse Sentido

A otimização de rota é a base. Uma vez que esteja funcionando, as extensões naturais são:

A página de Indústria de Logística e Entrega e a página de Indústria de Gerenciamento de Frotas cobrem recursos MapAtlas adicionais relevantes para software de despacho, incluindo VRP multi-veículo e otimização de retorno ao depósito.

Começando

Frequently Asked Questions

How does route optimisation reduce delivery costs?

Route optimisation reorders multi-stop delivery sequences to minimise total distance and drive time. Studies consistently show 20–35% reductions in distance driven versus a naive sequential route. For a vehicle driving 200 km/day at €0.35/km fuel cost, a 30% reduction saves around €21 per vehicle per day, roughly €5,000 per year per vehicle.

What are time windows in route optimisation?

Time windows are delivery constraints that require a stop to be visited within a specified time range, for example, a business that accepts deliveries only between 09:00 and 12:00. The optimiser must respect all time windows while still minimising total route distance, which is a significantly harder computational problem than unconstrained optimisation.

Does the MapAtlas Routing API handle EU Low Emission Zones?

Yes. The MapAtlas Routing API includes road restriction data for EU Low Emission Zones including Amsterdam's ZTL, the Paris Crit'Air zone, and Berlin's Umweltzone. Pass the vehicle profile (diesel Euro 5, petrol, electric) as a parameter and the router will automatically avoid restricted zones for non-compliant vehicles.

Perguntas frequentes

Como a otimização de rotas reduz os custos de entrega?

A otimização de rotas reordena as sequências de entrega com múltiplas paradas para minimizar a distância total e o tempo de condução. Estudos mostram consistentemente reduções de 20 a 35 por cento na distância percorrida em comparação com uma rota sequencial sem otimização. Para um veículo rodando 200 km/dia com custo de combustível de 0,35 EUR/km, uma redução de 30 por cento economiza cerca de 21 EUR por veículo por dia, aproximadamente 5.000 EUR por ano por veículo.

O que são janelas de tempo na otimização de rotas?

Janelas de tempo são restrições de entrega que exigem que uma parada seja visitada dentro de um intervalo de tempo especificado, por exemplo, uma empresa que aceita entregas apenas entre 09h00 e 12h00. O otimizador deve respeitar todas as janelas de tempo enquanto minimiza a distância total da rota, o que é um problema computacional significativamente mais difícil do que a otimização sem restrições.

A MapAtlas Routing API lida com as Zonas de Baixas Emissões da UE?

Sim. A MapAtlas Routing API inclui dados de restrições viárias para Zonas de Baixas Emissões (LEZ) da UE, incluindo a ZTL de Amsterdã, a zona Crit'Air de Paris e a Umweltzone de Berlim. Passe o perfil do veículo (diesel Euro 5, gasolina, elétrico) como parâmetro e o roteador evitará automaticamente zonas restritas para veículos não conformes.

Achou útil? Compartilhe.

Sobre o autor

Brent van der Heiden

Escrito por

Brent van der Heiden

Co-Founder & CEO at MapAtlas

Brent built MapAtlas out of a conviction that developers deserve location APIs with fair pricing and genuine end-user privacy. He writes about geospatial infrastructure, AI search visibility, and how location data powers the products people rely on every day.

Ver todos os artigos
Voltar ao blog