Giao hàng tại điểm cuối là phần đắt nhất của bất kỳ chuỗi cung ứng nào. Các tiêu chuẩn ngành luôn đặt chi phí giao hàng tại điểm cuối ở mức 53% tổng chi phí vận chuyển. Trong đó, biến kiểm soát lớn nhất là hiệu quả tuyến đường. Người lái hoàn thành 15 điểm dừng theo thứ tự sai có thể lái nhiều hơn 40% km hơn cần thiết, tiêu thụ nhiên liệu, làm hỏng xe và bỏ lỡ các cửa sổ thời gian giao hàng gây ra phí giao hàng lại.
Tối ưu hóa tuyến đường không còn là vấn đề khó để giải quyết trong mã nữa. Cái gì trước đây yêu cầu phần mềm hậu cần chuyên biệt đắt tiền hiện là một lệnh gọi API. Hướng dẫn này xây dựng một trình tối ưu hóa tuyến đường nhiều điểm dừng hoàn chỉnh bằng cách sử dụng API Định Tuyến MapAtlas: một kịch bản Python gửi danh sách các điểm dừng giao hàng, nhận lại một chuỗi được tối ưu hóa với khoảng cách và thời gian tổng cộng, áp dụng các ràng buộc cửa sổ thời gian và xử lý các hạn chế Vùng Phát Thải Thấp EU cho giao hàng đô thị. Một đoạn mã JavaScript sau đó vẽ kết quả trên bản đồ.
Triển khai Python dưới 55 dòng. Màn hình bản đồ JavaScript là 30 dòng bổ sung.
Vấn Đề Chi Phí Tại Điểm Cuối
Để hiểu những gì tối ưu hóa thực sự tiết kiệm, chạy các con số cho một kịch bản giao hàng thực tế:
- Đội xe: 10 chiếc xe tải
- Điểm dừng mỗi xe tải mỗi ngày: 18
- Khoảng cách trung bình hiện tại: 210 km/xe tải/ngày
- Chi phí nhiên liệu: €0,38/km (dầu diesel, trung bình EU)
- Chi phí người lái: €22/giờ
- Thời gian tuyến đường hiện tại trung bình: 7,5 giờ/ngày
Chi phí hàng ngày hiện tại trên mỗi xe tải: (210 × €0,38) + (7,5 × €22) = €79,80 + €165 = €244,80/xe tải/ngày
Giảm khoảng cách 30% (đạt được bằng tối ưu hóa tốt trên mạng đô thị dày đặc) và tiết kiệm thời gian 20% tạo ra:
- Khoảng cách được tối ưu hóa: 147 km, chi phí nhiên liệu: €55,86
- Thời gian được tối ưu hóa: 6 giờ, chi phí người lái: €132
- Chi phí hàng ngày được tối ưu hóa trên mỗi xe tải: €187,86/xe tải/ngày
Tiết kiệm trên mỗi xe tải mỗi ngày: €56,94. Cho 10 xe tải trong 250 ngày làm việc: €142.350/năm, từ một tích hợp API.
Các tiêu chuẩn ở trên phản ánh các số liệu được công bố thực tế từ các nghiên cứu hậu cần tại điểm cuối. Các con số cụ thể của bạn sẽ khác nhau theo địa lý, loại xe và mật độ dừng. Các khu vực đô thị dày đặc có lợi ích lớn nhất vì các tuyến đường theo thứ tự ngây thơ lãng phí khoảng cách lớn nhất trên việc quay trở lại không cần thiết.
So Sánh Tuyến Đường Ngây Thơ Và Được Tối Ưu Hóa: So Sánh Trực Quan
Sự khác biệt giữa tuyến đường ngây thơ (tuần tự) và tuyến đường được tối ưu hóa là rõ ràng trên bản đồ.
Định tuyến ngây thơ xảy ra khi bạn cung cấp dừng theo thứ tự chúng được nhập, khách hàng đầu tiên đặt hàng là người đầu tiên trên tuyến đường, bất kể địa lý. Ở một thành phố như Amsterdam hoặc Berlin, điều này tạo ra vấn đề "tuyến đường mì Ý": người lái của bạn liên tục vượt con đường của chính họ.
Tối ưu hóa giải quyết Vấn Đề Người Bán Hàng Du Lịch (TSP) cho bộ điểm dừng của bạn. Đối với 15–20 dừng, điều này có thể tính toán được trong phút. Đối với các đội xe lớn hơn có hàng trăm điểm dừng, các bộ giải quyết vấn đề định tuyến xe (VRP) xử lý các ràng buộc bổ sung của nhiều xe và giới hạn dung lượng.
Step 1: Structure Your Delivery Data
Each stop needs a location and, for time-windowed deliveries, a time_window specifying when the delivery is acceptable.
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" } }
]
Step 2: Call the Route Optimisation Endpoint
POST the depot and stop list to the optimised routing endpoint. The API returns the stops in the most efficient visit order along with the total route distance and duration.
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)
Step 3: Parse and Display the Optimised Route
The API response includes the stops in optimised order, cumulative ETAs for each stop, total distance, and total duration.
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)
Sample output for the five stops above:
--- Optimised Route Summary ---
Total distance : 38.4 km
Total duration : 94 min
Stops : 5
START Warehouse - Sloterdijk
1. Vondelpark Paviljoen ETA 07:48 (on time)
2. Café De Jaren ETA 08:31 (on time)
3. Albert Heijn Jordaan ETA 09:15 (on time)
4. Hotel V Nesplein ETA 10:02
5. Westergasfabriek Events ETA 10:44 (on time)
END Warehouse - Sloterdijk
Estimated fuel saving vs sequential: 14.2 km (27%)
Step 4: EU Low Emission Zone Handling
Amsterdam's ZTL zone, Paris's Crit'Air system, and Berlin's Umweltzone restrict certain vehicle types from central areas at specified times. A route that looks efficient on distance alone may be invalid for your vehicle.
The avoid_low_emission_zones: true parameter combined with the vehicle_profile automatically routes around restricted zones for non-compliant vehicles. For electric and Euro 6 vehicles, LEZs are passable and the parameter has no effect.
# Example: diesel Euro 5 van, will be re-routed around Amsterdam ZTL
result_euro5 = optimise_route(depot, stops, vehicle_profile="van-diesel-euro5")
# Example: electric van, LEZ restrictions do not apply
result_electric = optimise_route(depot, stops, vehicle_profile="electric-van")
print(f"Euro 5 route distance : {result_euro5['route']['total_distance_km']:.1f} km")
print(f"Electric route distance: {result_electric['route']['total_distance_km']:.1f} km")
# Electric route will typically be shorter as it can use LEZ-restricted roads
For logistics operations planning a transition from diesel to electric, comparing these two outputs per route provides a direct quantification of the range improvement available from electrification.
Step 5: Display the Optimised Route on a Map
Take the route geometry from the API response and render it as a line layer in 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);
Calculating Your Real Savings
Once you have the API response in hand, the saving calculation is straightforward. The saving_vs_naive_km field in the response gives you distance saved directly. From that, derive cost savings:
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)
Time Window Optimisation
Delivering to a bakery at 06:00 and a restaurant at 14:00 while minimising total route distance is a constrained optimisation problem. The API handles this automatically, you only need to provide the windows:
# Time-sensitive stops, the API will schedule these within their windows
stops_with_windows = [
{ "lat": 52.3726, "lng": 4.8971, "name": "Bakery",
"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": "Restaurant",
"time_window": { "start": "13:00", "end": "15:00" } }
]
If any time window constraint cannot be satisfied given the depot departure time and current traffic model, the API returns a constraint_violations array listing which stops could not be reached on time. Your dispatch software can then alert the driver or suggest an earlier departure.
Những Gì Để Xây Dựng Ở Trên Này
Tối ưu hóa tuyến đường là nền tảng. Khi nó đang chạy, các tiện ích mở rộng tự nhiên là:
- Theo dõi người lái trực tiếp: Cấp tọa độ tuyến đường được tối ưu hóa cho Hướng dẫn Bản Đồ Theo Dõi Người Lái Trực Tiếp và hiển thị cập nhật ETA thời gian thực cho khách hàng.
- Lập kế hoạch phạm vi dựa trên Isochrone: Sử dụng API Thời Gian Du Lịch để trực quan hóa mã bưu chính nào đội xe của bạn có thể tiếp cận trong cửa sổ giao hàng. Bài viết Bản Đồ Isochrone Giải Thích cho thấy cách thực hiện.
- Xác thực địa chỉ hàng loạt: Trước khi chạy tối ưu hóa, hãy xác thực tất cả các địa chỉ giao hàng bằng API Địa Mã Hóa để bắt lỗi gõ và mã bưu chính lỗi thời. Xem Cách Sử Dụng API Địa Mã Hóa Để Xác Thực 10.000 Địa Chỉ Hàng Loạt.
Trang ngành Hậu Cần Và Giao Hàng và Trang ngành Quản Lý Đội Xe bao gồm các tính năng MapAtlas bổ sung phù hợp với phần mềm phân tán, bao gồm VRP nhiều xe và tối ưu hóa trở về kho.
Bắt Đầu
- Đăng ký khóa API MapAtlas miễn phí, tầng miễn phí bao gồm các lệnh gọi định tuyến và tối ưu hóa, không cần thẻ tín dụng
- Xem lại Tài Liệu API Định Tuyến để có danh sách đầy đủ các hồ sơ xe, tham số cửa sổ thời gian và các tùy chọn nhiều xe
- Khám phá Trang Khả Năng Lập Kế Hoạch Tuyến Đường Và Điều Hướng để có cái nhìn tổng quan về sản phẩm
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.
Câu hỏi thường gặp
Tối ưu hóa tuyến đường giảm chi phí giao hàng như thế nào?
Tối ưu hóa tuyến đường sắp xếp lại trình tự các điểm dừng giao hàng để giảm thiểu tổng quãng đường và thời gian lái xe. Các nghiên cứu liên tục cho thấy mức giảm 20 đến 35 phần trăm quãng đường so với tuyến đường tuần tự thông thường. Với xe chạy 200 km mỗi ngày và chi phí nhiên liệu 0,35 EUR/km, giảm 30 phần trăm tiết kiệm khoảng 21 EUR mỗi xe mỗi ngày, tương đương khoảng 5.000 EUR mỗi năm trên mỗi xe.
Khung thời gian trong tối ưu hóa tuyến đường là gì?
Khung thời gian là các ràng buộc giao hàng yêu cầu điểm dừng phải được ghé thăm trong một khoảng thời gian cụ thể, ví dụ một doanh nghiệp chỉ nhận hàng từ 09:00 đến 12:00. Bộ tối ưu hóa phải tuân thủ tất cả các khung thời gian trong khi vẫn giảm thiểu tổng khoảng cách tuyến đường, đây là bài toán tính toán phức tạp hơn nhiều so với tối ưu hóa không ràng buộc.
MapAtlas Routing API có xử lý Vùng Phát thải Thấp EU không?
Có. MapAtlas Routing API bao gồm dữ liệu hạn chế đường cho các Vùng Phát thải Thấp (LEZ) của EU, bao gồm ZTL Amsterdam, vùng Crit'Air Paris và Umweltzone Berlin. Truyền hồ sơ xe (diesel Euro 5, xăng, điện) làm tham số và router sẽ tự động tránh các khu vực bị hạn chế đối với xe không tuân thủ.

