Let's Use Pyroutelib3!

pyroutelib3를 사용해보자

Featured image

HD Map 정보를 publishing 해주는 패키지를 구상할때, 원래는 global path planning까지 구현할 예정이였다.

그러나 1차년도 계획에서는 지정된 셔틀 경로만 주행하기로 결정되며, global path planning은 하지 않았다.

몇 가지 공개된 툴을 이용하여 path planning을 시도하였으나, 실제 자율주행에 바로 적용하기에는 주행 방향을 고려하지 않는 문제 등으로 인하여 개발이 중단되었었다.

이번에 기존의 HD Map package의 문제점을 보완한 새로운 package 개발을 준비하며, path planing까지 구현하고자 한다.

몇 가지의 툴을 이용해본 결과, 우리 HD map package와 호환성이 높으면서도 개발하기 용이하다고 판단된 pyroutelib3를 사용하기로 결정하였다.

pyroutelib3를 사용해보고, 추가 개발이 필요한 부분을 정리하였다.

pyroutelib3

pyroutelib3는 pyroutelib2를 기반으로 만들어졌다.

pyroutelib2는 온라인 상의 Openstreet Map을 이용하여 경로를 생성하는데, pyroutelib3는 로컬 osm 파일을 이용할 수 있다.

우리 상황에 맞게 이용하기 위하여, 코드를 약간 수정하여 테스트하였다.

기본 실행 코드는 아래와 같다.

from pyroutelib3 import Router # Import the router
router = Router("<transport mode>", "<path-to-.osm-file>")

start = router.findNode(lat, lon) # Find start and end nodes
end = router.findNode(lat, lon)

status, route = router.doRoute(start, end) # Find the route - a list of OSM nodes

if status == 'success':
    routeLatLons = list(map(router.nodeLatLon, route)) # Get actual route coordinates

"<transport mode>""car"로 설정하였고, "<path-to-.osm-file>"은 테크노폴리스 일대의 주행유도선 파일로 설정하였다.

출발점과 도착점은 임의의 두 지점을 찍어서 위도와 경도를 입력하였다.

이렇게 단순히 실행을 하면 KeyError("findNode in an empty space")가 발생한다.

Transport mode가 car인 경우, 아래와 같이 weights가 설정되어있다.

"weights": {
    "motorway": 10, "trunk": 10, "primary": 2, "secondary": 1.5, "tertiary": 1,
    "unclassified": 1, "residential": 0.7, "living_street": 0.5, "track": 0.5,
    "service": 0.5,
}

way의 tag에 각 키워드가 있으면 이를 파싱하여 weight를 설정하는데, 국토지리정보원에서 제공하는 정밀도로지도는 Openstreet Map 규격에 맞추어져 있지 않기 때문에 위와 같은 문제가 발생하는 것이다.

테크노폴리스 일대는 다 똑같은 일반도로이기 때문에, 굳이 weight을 다르게 설정할 필요가 없다.

Weight은 osmparsing.py 파일의 getWayWeight에서 부여하는데, 이때의 return 값을 10으로 고정하였다.

image1

그러고 나서 재실행하면 작동은 하는데 딱히 결과값을 보여주지는 않는다.

단순 확인을 위해 시각화하는 부분까지 짜기는 귀찮으므로,, JOSM에 바로 import하여 눈으로 확인할 수 있도록 복사하기 쉬운 형태로 planning된 경로의 위도, 경도를 출력하도록 설정하였다.

최종 실행 코드는 아래와 같아졌다.

from pyroutelib3 import Router # Import the router
router = Router("car", "A2_LINK.osm") # Initialise it

start = router.findNode(35.7011876, 128.4585397)
end = router.findNode(35.6913484, 128.4639248)

status, route = router.doRoute(start, end) # Find the route - a list of OSM nodes

if status == 'success':
    routeLatLons = list(map(router.nodeLatLon, route)) # Get actual route coordinates
    for latlon in routeLatLons:
        print(str(latlon)[1:-1])

이제 실행해보면, 아래와 같이 주르륵 뜬다.

image2

이걸 복사한 뒤, JOSM의 Lat Lon Tool을 이용하여 시각화하였다.

image3

이렇게 보면 얼추 잘된 것 같아보이지만…

image4

가까이서 보면 역주행을 하고… 이상하게 주행하는 것을 확인할 수 있다.

불완전한 Path Planning 원인 파악

그래서 위와 같이 결과가 나오는 원인을 파악해보았다.
파악된 원인은 아래와 같다.

1. 역주행을 금지하지 않는다.

2. way로 node간 연결이 되어있지 않은 경우, 차선변경을 하지 못한다.

TODO

위 문제를 해결하기 위해서 아래와 같은 작업을 진행할 예정이다.

image5

최종 주행유도선 맵 파일은 위 그림과 같이 구현할 예정이다.