Contents

แสดงเส้นทางบนแผนที่ด้วย Open Source Routing Machine (OSRM)

บทความนี้แสดงวิธีติดตั้งและใช้งาน Open Source Routing Machine (OSRM) 1 ระบบโอเพ่นซอร์สสำหรับค้นหาเส้นทางบนแผนที่ โดยใช้ข้อมูลจาก OpenStreetMap (OSM) 2

เนื้อหาเน้นไปที่การตั้งค่า ระบบ OSRM ฝั่งเซิร์ฟเวอร์ (Backend) เพื่อให้สามารถคำนวณระยะทาง เวลาเดินทาง หรือเส้นทางที่เหมาะสมระหว่างพิกัดต่างๆ ได้ผ่าน REST API

โดยจะแบ่งเนื้อหาออกเป็น 4 ส่วนหลัก:

  1. ดาวน์โหลดข้อมูลแผนที่ของประเทศไทยจาก OSM
  2. เตรียมข้อมูลให้เหมาะกับอัลกอริทึมของ OSRM (CH 3 หรือ MLD 4 5)
  3. สร้างและเปิดใช้งานระบบ OSRM
  4. ทดสอบการคำนวณระยะทางและระยะเวลา
  5. ทดสอบการคำนวณเส้นทาง

1. ดาวน์โหลดข้อมูลแผนที่ของประเทศไทยจาก OpenStreetMap

ก่อนใช้งาน OSRM จำเป็นต้องมีข้อมูลแผนที่ที่ประกอบด้วยโครงสร้างถนน บทความนี้แนะนำการดาวน์โหลดข้อมูล OSM ของประเทศไทยจาก 2 แหล่ง:

1.1 ดาวน์โหลดจาก slice.openstreetmap.us 6

  1. เปิดเว็บไซต์ แล้วกรอก GeoJSON ของประเทศไทยลงในช่อง Paste bbox or GeoJSON:
  2. คลิก Load เพื่อโหลดขอบเขตข้อมูล (รูปที่ 1)
  3. คลิก Generate Slice รอจนระบบประมวลผลเสร็จ
  4. คลิก Download เพื่อดาวน์โหลดไฟล์ข้อมูล
  5. เปลี่ยนชื่อไฟล์เป็น thailand-latest.osm.pbf

ℹ️ หมายเหตุ: เว็บไซต์นี้เหมาะสำหรับผู้ที่ต้องการเลือกพื้นที่แผนที่เฉพาะ เช่น รายจังหวัด หรือเฉพาะจุดที่สนใจ และต้องการข้อมูลที่อัปเดตเร็วภายในไม่กี่นาที สามารถดาวน์โหลดตัวอย่างไฟล์ GeoJSON ของประเทศไทยได้ที่ลิงก์นี้

/images/2025-04-01/example_slice_thailand_osm_data_from_slice_openstreetmap_us.png
รูปที่ 1 แสดงตัวอย่างข้อมูลแผนที่ประเทศไทยที่ถูกตัดเฉพาะจาก OpenStreetMap โดยใช้เว็บไซต์ slice.openstreetmap.us

1.2 ดาวน์โหลดจาก Geofabrik 7

Geofabrik แบ่งข้อมูล OSM ตามประเทศไว้เรียบร้อย สามารถเลือกดาวน์โหลดไฟล์ thailand-latest.osm.pbf ได้ทันที โดยไฟล์อัปเดตทุกวัน

ข้อมูลในเว็บไซต์นี้จะมีการปรีบปรุงวันละ 1 ครั้ง โดยจะมีการระบุวันและเวลาที่ข้อมูล OSM ของไฟล์ thailand-latest.osm.pbf ถูกสร้างขึ้น 8

ตัวอย่างคำสั่ง:

VERSION=latest
wget http://download.geofabrik.de/asia/thailand-${VERSION}.osm.pbf

ℹ️ หมายเหตุ: ไฟล์ -latest จะถูกอัปเดตทุกวัน แต่หากต้องการความสามารถในการติดตามเวอร์ชันย้อนหลัง สามารถเลือกดาวน์โหลดตามวันที่ได้ เช่น thailand-240401.osm.pbf

2. เตรียมข้อมูล OSM ให้กับระบบ OSRM ใช้งาน

ข้อมูลที่ดาวน์โหลดมา ต้องผ่านขั้นตอนการเตรียมให้เหมาะกับอัลกอริทึมของ OSRM โดยแบ่งออกเป็น:

2.1 แยกข้อมูลด้วย osrm-extract

ตัวอย่างคำสั่งสำหรับแยกข้อมูลด้วยโปรไฟล์รถยนต์:

docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend \
    osrm-extract -p /opt/car.lua /data/thailand-${VERSION}.osm.pbf \
    || echo "osrm-extract failed"

💡 หมายเหตุ: ไฟล์ car.lua เป็นไฟล์ที่กำหนดวิธีการคำนวณเส้นทางเดินทาง เช่น ตั้งค่าให้หลีกเลี่ยงทางด่วน หรือกำหนดความเร็วสูงสุดตามประเภทของถนน เช่น ถนนหลวง ถนนในเมือง หรือถนนลูกรัง คำสั่งที่ใช้ด้านบนจะอ้างอิงไฟล์ car.lua แบบค่าเริ่มต้น (default) สามารถดูรายละเอียดของไฟล์นี้เพิ่มเติมได้ที่ลิงก์นี้

2.2 เตรียมข้อมูลตามอัลกอริทึมที่เลือกใช้

OSRM รองรับ 2 อัลกอริทึม:

  • Contraction Hierarchies (CH)
  • Multi-Level Dijkstra (MLD)

เลือกใช้เพียงแบบใดแบบหนึ่งเท่านั้น:

CH:

docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend \
    osrm-contract /data/thailand-${VERSION}.osrm \
    || echo "osrm-contract failed"

MLD:

docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend \
    osrm-partition /data/thailand-${VERSION}.osrm \
    || echo "osrm-partition failed"

docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend \
    osrm-customize /data/thailand-${VERSION}.osrm \
    || echo "osrm-customize failed"

3. เปิดใช้งาน OSRM ผ่าน REST API

เปิดใช้เซิร์ฟเวอร์ OSRM ตามอัลกอริทึมที่เตรียมไว้ในขั้นตอนที่ 2:

CH:

docker run -t -i -p 5000:5000 -v "${PWD}:/data" \
    ghcr.io/project-osrm/osrm-backend \
    osrm-routed --algorithm ch /data/thailand-${VERSION}.osrm

MLD:

docker run -t -i -p 5000:5000 -v "${PWD}:/data" \
    ghcr.io/project-osrm/osrm-backend \
    osrm-routed --algorithm mld /data/thailand-${VERSION}.osrm

ℹ️ หมายเหตุ: ค่าเริ่มต้นของ osrm-routed คือจะเปิด REST API บนเครื่อง localhost ที่พอร์ต 5000 ทำให้สามารถเข้าถึงการคำนวณเส้นทางได้ผ่าน URL http://localhost:5000.

4. การทดสอบการคำนวณระยะทางระหว่างสองจุดบนแผนที่ด้วย OSRM ผ่าน REST API

เพื่อคำนวณระยะทางและระยะเวลา เช่น จากจุฬาลงกรณ์มหาวิทยาลัยไปมหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรี สามารถใช้ API /table เพื่อสำหรับการหาค่าระยะทางที่เร็วที่สุดด้วยพาธ (path) /table/v1/driving 9 และพารามิเตอร์จุดเริ่มต้นและจุดหมายปลายทาง พร้อมกับพารามิเตอร์ annotations=duration,distance

ข้อควรระวัง

  • พิกัดจะต้องระบุค่าลองจิจูดก่อน และตามด้วยลัตติจูด
  • พิกัดแรกคือจุดเริ่มต้นและพิกัดถัดไปคือจุดหมายปลายทาง

ตัวอย่างคำสั่ง cURL เพื่อคำนวณระยะทางระหว่างจุฬาลงกรณ์มหาวิทยาลัยและมหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรี:

CHULA=100.5261394,13.7389135
KMUTT=100.4964428,13.6512522
curl --location "http://localhost:5000/table/v1/driving/${CHULA};${KMUTT}?annotations=duration%2Cdistance"

ผลลัพธ์ที่ได้จะประกอบด้วยระยะทางและระยะเวลาไป-กลับ โดยค่าผลลัพธ์ตัวอย่างแสดงถึง:

  • ระยะทางจากจุฬาลงกรณ์มหาวิทยาลัยไปมหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรี คือ 13,349.6 เมตร
  • ระยะเวลาที่ใช้จากจุฬาลงกรณ์มหาวิทยาลัยไปมหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรี คือ 845.9 วินาที

และ

  • ระยะทางจากมหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรีกลับไปจุฬาลงกรณ์มหาวิทยาลัย คือ 13,542.4 เมตร
  • ระยะเวลาที่ใช้จากมหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรีกลับไปจุฬาลงกรณ์มหาวิทยาลัย คือ 863.3 วินาที

ผลลัพธ์ JSON:

{
    "code": "Ok",
    "distances": [
        [
            0,
            13349.6
        ],
        [
            13542.4,
            0
        ]
    ],
    "durations": [
        [
            0,
            845.9
        ],
        [
            863.3,
            0
        ]
    ],
    "destinations": [ ...
    ],
    "sources": [ ...
    ]
}

5. การทดสอบการคำนวณเส้นทางระหว่างสองจุดบนแผนที่ด้วย OSRM ผ่าน REST API

การคำนวณหาเส้นทางที่เร็วที่สุดสามารถใช้ API /route หรือ /route/v1/driving/ 10 ตามด้วยพารามิเตอร์ของจุดเริ่มต้นและตามด้วยจุดหมายปลายทาง

ตัวอย่างคำสั่ง cURL เพื่อคำนวณหาเส้นทางระหว่างจุฬาลงกรณ์มหาวิทยาลัยและมหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรี:

curl --location "http://localhost:5000/route/v1/driving/${CHULA};${KMUTT}"

ผลลัพธ์ที่ได้จะประกอบด้วยระยะทาง, ระยะเวลา และเส้นทางจากจุดเริ่มต้นไปยังจุดหมายปลายทางโดยเส้นทางแสดงผลลัพธ์ในข้อมูลของ geometry ในรูปแบบ polyline:

  • เส้นทางจากจุฬาลงกรณ์มหาวิทยาลัยไปมหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรี คือ ghzrA}~pdRuBbWdTbCzOzTf_@nB`Yk@nv@sMzt@dI~Qe@hTuIda@sc@tHgA|OdQfpBrwA`TsXmQz]vEjRbv@rStr@p^bM|A?dGYmE

ผลลัพธ์ JSON:

{
    "code": "Ok",
    "routes": [
        {
            "geometry": "ghzrA}~pdRuBbWdTbCzOzTf_@nB`Yk@nv@sMzt@dI~Qe@hTuIda@sc@tHgA|OdQfpBrwA`TsXmQz]vEjRbv@rStr@p^bM|A?dGYmE",
            "legs": [
                {
                    "steps": [],
                    "summary": "",
                    "weight": 845.9,
                    "duration": 845.9,
                    "distance": 13349.6
                }
            ],
            "weight_name": "routability",
            "weight": 845.9,
            "duration": 845.9,
            "distance": 13349.6
        }
    ],
    "waypoints": [ ...
    ]
}

สามารถนำ polyline ไปวาดลงบนแผนที่ได้หลากหลายวิธี ในที่นี้จะแสดง 2 วิธี:

  1. วาดเส้นทางที่เว็บไซต์ valhalla.github.io/demos/polyline หรือ developers.google.com/maps/documentation/routes/polylinedecoder
  2. เขียนโปรแกรม Python และใช้ folium library เพื่อวาดเส้นทางลงใน Python Notebook

5.1.1 วาดเส้นทางบนเว็บไซต์ valhalla.github.io/demos/polyline

เปิดเว็บไซต์แล้วกรอกผลลัพธ์ polyline ที่ได้ ในตัวอย่างข้างต้น คือ ghzrA}~pdRuBbWdTbCzOzTf_@nB`Yk@nv@sMzt@dI~Qe@hTuIda@sc@tHgA|OdQfpBrwA`TsXmQz]vEjRbv@rStr@p^bM|A?dGYmE ลงในช่อง Encoded Line (กรอบสีแดง) ระบบจะแสดงผลเส้นทาง (เส้นสีม่วง) ตามตัวอย่างดังรูปที่ 2

/images/2025-04-01/example_render_polyline_on_valhalla_github_demos_polyline.png
รูปที่ 2 แสดงเส้นทางจากจุฬาลงกรณ์มหาวิทยาลัยไปมหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรีด้วยเส้นสีม่วง

⚠️ หมายเหตุ: พบว่าบางครั้ง polyline ที่แสดงผลด้วยเว็บไซต์ข้างต้น11 ไม่ถูกต้อง

5.1.2 วาดเส้นทางบนเว็บไซต์ developers.google.com/maps/documentation/routes/polylinedecoder

เปิดเว็บไซต์แล้วกรอกผลลัพธ์ polyline ที่ได้ ในตัวอย่างข้างต้น คือ ghzrA}~pdRuBbWdTbCzOzTf_@nB`Yk@nv@sMzt@dI~Qe@hTuIda@sc@tHgA|OdQfpBrwA`TsXmQz]vEjRbv@rStr@p^bM|A?dGYmE ลงในช่อง Encoded ployline และกดปุ่ม Decode ระบบจะแสดงผลเส้นทาง (เส้นน้ำเงิน) ตามตัวอย่างดังรูปที่ 3

/images/2025-04-01/example_render_polyline_on_developers_google_maps_documentation_routes_polylinedecoder.png
รูปที่ 3 แสดงเส้นทางจากจุฬาลงกรณ์มหาวิทยาลัยไปมหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรีด้วยเส้นสีน้ำเงิน

5.2 วาดเส้นทางบนแผนที่ด้วยโปรแกรม Python 12

ด้านล่างคือตัวอย่างโปรแกรม Python ที่แสดงการเส้นทาง:

  1. เรียกข้อมูลเส้นทางจากเซิร์ฟเวอร์ OSRM (ในข้อที่ 3) ด้วย REST API ที่ http://localhost:5000/route/v1/driving
  2. แสดงเส้นทางบนแผนที่ด้วยไลบรารี folium โดยใช้ข้อมูล polyline ที่ได้จาก OSRM
import requests
import folium
from folium.plugins import PolyLineFromEncoded

# request route from a local osrm server
CHULA=[100.5261394,13.7389135]
KMUTT=[100.4964428,13.6512522]

# make the request to the OSRM server
osrm_request_url = f"http://localhost:5000/route/v1/driving/{CHULA[0]},{CHULA[1]};{KMUTT[0]},{KMUTT[1]}"
response = requests.get(osrm_request_url)
data = response.json()

# extract the polyline from the response
encoded_polyline = data['routes'][0]['geometry']

# create a folium map centered at the midpoint of CHULA and KMUTT
m = folium.Map(location=[(CHULA[1]+KMUTT[1])/2.,(CHULA[0]+KMUTT[0])/2.], zoom_start=13)

# draw an encoded polyline on a map
PolyLineFromEncoded(encoded=encoded_polyline).add_to(m)
m