SUMO 이야기

[SUMO 이야기] #6. SUMO 튜토리얼: Traci를 활용한 시뮬레이션 제어

교통앵무 2024. 3. 31. 16:33

자 이제 실전이다. 지금부터는 netedit이고 뭐고 전혀 다른 세계가 펼쳐질 예정이다(사실 쉬움).

 

 

각설하고, 아주 간단한 sumo 실행 코드를 다음과 같이 작성할 수 있다.

import traci

def simulation():
    # Directory
    sumo_binary = "/sumo/bin/sumo" # or sumo-gui
    sumocfg_dir = "/run.sumocfg"
    route_dir = "/temp.rou.xml"

    # Run SUMO
    sumo_cmd = [sumo_binary, "-c", sumocfg_dir, "-r", route_dir, "--junction-taz", "--no-warnings", "--random"]
    traci.start(sumo_cmd)

    # Set variables
    time = 0
    reroute_freq = 10
    
    # Running ...
    while traci.simulation.getMinExpectedNumber() > 0:
        traci.simulationStep()
        time += 1
        if time // reroute_freq == 0:
            for vid in traci.simulation.getDepartedIDList():
                traci.vehicle.rerouteTraveltime(vid)

        # Close SUMO
        if time > 300:
            traci.close()
            break
            
    return 0

 

  • sumo_binary에는 sumo를 설치한 경로를 기입한다. 시뮬레이션을 시각적으로 확인하고 싶다면 sumo가 아닌 sumo-gui를 끝에 입력한다.

 

  • sumocfg_dir에는 실행하고자 하는 configuration 파일의 경로를, route_dir에는 rou.xml 파일의 경로를 넣어준다.
    • route file을 명령어에 따로 넣어주는 이유는 같은 네트워크에 다른 route file을 새롭게 덮어씌워 가면서 적용할 필요가 있는 경우에 이렇게 한다.

 

  • --junction-taz, --no-warnings, --random 같은 경우에는 옵션이므로 필요한 경우 구글링하여 원하는 옵션을 넣어주면 된다.
    • --junction-taz는 taz 형태로 수요를 넣어줄 때 필요한 옵션이다.
    • --no-warnings는 귀찮은 오류들을 터미널에 표시하는 것을 막는다.
    • --random은 random seed를 무작위로 선정하여 시뮬레이션에 랜덤성을 가한다.

 

  • reroute_freq는 몇 초마다 차량을 reroute할건지 정해주기 위해 만든 변수로, 위 코드에서는 간단하게 가장 작은 통행비용을 갖는 경로로 차량이 10초마다 재배치되도록 설정하였다.

 

  • while traci.simulation.getMinExpectedNumber() > 0: 는 시뮬레이션 내 차량 수가 0보다 크지 않을 때까지 계속해서 시뮬레이션을 구동한다는 의미이다.
    • 기본적으로 SUMO는 step 단위(frame이라고 생각하면 된다)로 돌아가기 때문에, traci.simulationStep()이 한 번 호출되면 1초의 시간이 흐른다.
    • 즉, route file에서 차량만 계속 공급해준다면 while문에 의해 시뮬레이션은 계속 돌아갈 것이다
    • 이때 종료조건을 만들어주기 위해, time 변수를 설정하여 루프가 돌 때마다 1씩 증가하고, 300초에 도달하게 되면 traci.close()함수로 시뮬레이션을 종료해줄 수 있다.

 

simulation()

 

위와 같이 함수를 정의하고 호출하면, SUMO가 켜져서 돌아가고, 300초가 되면 알아서 종료된다.

 

시뮬레이션을 키고 끄는 기능을 먼저 알려주는 이유는, 이 함수를 바탕으로 아주 다양한 형식으로 시뮬레이션을 제어할 수 있기 때문이다.

 

예를 들어, xml 라이브러리를 이용해 직접 route file을 갱신시켜가며 시뮬레이션을 반복적으로 돌릴 수도 있고, 시뮬레이션을 돌려 생성된 detector data를 중간에 읽어들여 어떤 값이 나왔는지 확인할 수도 있다. 중간에 차량을 제어하고 싶다면 차량 id를 탐색하고 직접 지정하여 원하는 차량을 조종할 수도 있다.

 

이 이상은 연구자 혹은 사용자의 입맛에 따라 수정하는 것이기 때문에, 원하는 목적에 따라 함수를 만들고, traci 기능을 찾아 그때그때 넣어주면 된다. 처음 공부하면 많이 막막하므로, 간단한 예제를 다음과 같이 공개한다.

 

 

문  제

 

해  설

d)의 경우, detector data 결과로 산출되는 xml 파일에 직접 접근도 가능하다.