728x90
vroom과 OSRM을 이용한 TSP
저번 글에서 한번 해봤는 데... 뭔가 이상하군요.
그래서 내 머리로는 안되는 것 같아 툴의 도움을 받기로 했습니다.
우선 내가 강남구청에서 뭔가를 영업하는 영업 직원이고 오늘 하루 50 군데를 방문해야 한다고 했을 때,
TSP 가 어떤 식으로 구성 되는가에 대해서 알아보기로 했습니다.
1. TSP 를 위한 준비
1.1. vroom 설치
설치가 되었다고 보고,
https://tobee.tistory.com/entry/vroom-Vehicle-Routing-Open-source-Optimization-Machine
1.2. OSRM 실행
osrm-routed.exe %OSRM_HOME%\osrm_data\south_korea\south-korea-latest.osm
1.3 input.json 준비
강남구청에서 시작해서 강남구청으로 돌아오는 것으로 준비 해봤습니다.
{
"vehicles": [
{
"id": 1,
"start": [127.027621, 37.497942], // 강남구청 (출발점)
"end": [127.027621, 37.497942] // 강남구청 (도착점)
}
],
"jobs": [
{ "id": 1, "location": [127.035212, 37.495477] }, // 역삼1동
{ "id": 2, "location": [127.045126, 37.498431] }, // 역삼2동
{ "id": 3, "location": [127.027436, 37.510205] }, // 논현1동
{ "id": 4, "location": [127.025221, 37.516245] }, // 논현2동
{ "id": 5, "location": [127.066409, 37.499513] }, // 대치1동
{ "id": 6, "location": [127.062032, 37.492522] }, // 대치2동
{ "id": 7, "location": [127.046882, 37.489915] }, // 대치4동
{ "id": 8, "location": [127.040508, 37.498161] }, // 삼성1동
{ "id": 9, "location": [127.051553, 37.514139] }, // 삼성2동
{ "id": 10, "location": [127.061707, 37.496634] }, // 청담동
{ "id": 11, "location": [127.034794, 37.507503] }, // 신사동
{ "id": 12, "location": [127.021602, 37.513866] }, // 압구정동
{ "id": 13, "location": [127.037316, 37.495522] }, // 도곡1동
{ "id": 14, "location": [127.042979, 37.492641] }, // 도곡2동
{ "id": 15, "location": [127.057222, 37.507457] }, // 세곡동
{ "id": 16, "location": [127.059778, 37.482721] }, // 자곡동
{ "id": 17, "location": [127.051248, 37.476564] }, // 율현동
{ "id": 18, "location": [127.039653, 37.498994] }, // 개포1동
{ "id": 19, "location": [127.034097, 37.488837] }, // 개포2동
{ "id": 20, "location": [127.046734, 37.486172] }, // 개포4동
{ "id": 21, "location": [127.041748, 37.509745] }, // 논현1동
{ "id": 22, "location": [127.038188, 37.494878] }, // 역삼1동
{ "id": 23, "location": [127.048871, 37.498221] }, // 삼성1동
{ "id": 24, "location": [127.041187, 37.505308] }, // 신사동
{ "id": 25, "location": [127.022919, 37.517817] }, // 압구정동
{ "id": 26, "location": [127.049905, 37.496708] }, // 대치1동
{ "id": 27, "location": [127.053617, 37.487403] }, // 대치2동
{ "id": 28, "location": [127.058739, 37.496972] }, // 대치4동
{ "id": 29, "location": [127.051709, 37.508669] }, // 삼성2동
{ "id": 30, "location": [127.063031, 37.503671] }, // 청담동
{ "id": 31, "location": [127.045371, 37.487391] }, // 도곡1동
{ "id": 32, "location": [127.039102, 37.489985] }, // 도곡2동
{ "id": 33, "location": [127.056914, 37.509118] }, // 세곡동
{ "id": 34, "location": [127.064212, 37.488129] }, // 자곡동
{ "id": 35, "location": [127.047619, 37.487612] }, // 율현동
{ "id": 36, "location": [127.048714, 37.506603] }, // 개포1동
{ "id": 37, "location": [127.033219, 37.497418] }, // 개포2동
{ "id": 38, "location": [127.039881, 37.489802] }, // 개포4동
{ "id": 39, "location": [127.034607, 37.507405] }, // 논현2동
{ "id": 40, "location": [127.028774, 37.512234] }, // 논현1동
{ "id": 41, "location": [127.023587, 37.516785] }, // 신사동
{ "id": 42, "location": [127.046448, 37.491074] }, // 역삼2동
{ "id": 43, "location": [127.049489, 37.498019] }, // 대치1동
{ "id": 44, "location": [127.041298, 37.498793] }, // 삼성1동
{ "id": 45, "location": [127.054103, 37.507996] }, // 삼성2동
{ "id": 46, "location": [127.065716, 37.490374] }, // 청담동
{ "id": 47, "location": [127.034502, 37.492107] }, // 개포1동
{ "id": 48, "location": [127.032810, 37.490583] }, // 개포2동
{ "id": 49, "location": [127.045891, 37.488392] }, // 개포4동
{ "id": 50, "location": [127.048809, 37.507305] } // 도곡1동
]
}
2. TSP 실행
output.json 파일을 만들어 냅니다. 아래 명령어를 사용해 보고
vroom -i input.json -o output.json --osrm http://localhost:5000
안되면
vroom --help
vroom.exe -i \tsp\input.json -o \tsp\output.json -a "localhost" -p 5000
결과 파일 output.json이 만들어 졌을 것입니다.
3. TSP 경로 확인
경로를 확인하기 위해서 저번글에서 설치 한 http server를 실행 해야 합니다.
tsp_viewer.html
GPT 교수님께 물어서 만들었습니다. output.json 파일을 읽어서 지도에 표시 합니다.
<!DOCTYPE html>
<html>
<head>
<title>VROOM Output Map</title>
<!--
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
!-->
<link rel="stylesheet" href="leaflet.css" />
<style>
#map {
height: 100vh;
}
</style>
</head>
<body>
<div id="map"></div>
<!--
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
!-->
<script src="leaflet.js"></script>
<script src="output.json" type="application/json"></script>
<script>
// 지도 초기화
const map = L.map('map').setView([37.566535, 126.977969], 10); // 서울 중심 좌표
// OpenStreetMap 타일 추가
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19
}).addTo(map);
// VROOM Output.json 불러오기
fetch("output.json")
.then(response => response.json())
.then(data => {
// Marker 및 경로 시각화
data.routes.forEach(route => {
// 각 경로의 경로선
const coordinates = route.steps.map(step => [step.location[1], step.location[0]]);
const polyline = L.polyline(coordinates, { color: 'blue' }).addTo(map);
// 각 경로의 시작 및 끝 위치
L.marker(coordinates[0], { title: `Start - Route ${route.vehicle}` }).addTo(map);
L.marker(coordinates[coordinates.length - 1], { title: `End - Route ${route.vehicle}` }).addTo(map);
// 방문 지점 마커
route.steps.forEach((step, index) => {
L.marker([step.location[1], step.location[0]], {
title: `Step ${index + 1}: Job ${step.id}`
}).addTo(map);
});
});
// 지도 경계 조정
const allCoordinates = data.routes.flatMap(route =>
route.steps.map(step => [step.location[1], step.location[0]])
);
const bounds = L.latLngBounds(allCoordinates);
map.fitBounds(bounds);
})
.catch(err => console.error("Error loading output.json:", err));
</script>
</body>
</html>
디렉토리 구조는 다음과 같은 느낌?
결과는??
이상.
728x90
'프로그래밍 > GIS' 카테고리의 다른 글
[OSRM] Chat GPT와 함께하는 TSP - 5 시각 정보 강화 (1) | 2024.12.05 |
---|---|
[OSRM] Chat GPT와 함께하는 TSP - 4 (0) | 2024.12.04 |
vroom - Vehicle Routing Open-source Optimization Machine (0) | 2024.11.30 |
[OSRM] Chat GPT와 함께하는 TSP - 2 (2) | 2024.11.29 |
[OSRM] Chat GPT와 함께하는 TSP (0) | 2024.11.29 |