├── plots ├── hellooo.txt ├── time_vs_epoch_city1.png ├── time_vs_epoch_city3.png └── time_vs_epoch_model.png ├── .gitignore ├── requirements.txt ├── documentation ├── project_info.txt ├── PSAR4.pdf ├── patent1.pdf ├── patent2.pdf ├── psar3.pdf ├── psar5.pdf ├── PSAR2(1).pdf ├── test_loop.png ├── samplecity1.PNG ├── train_loop.png ├── Ideation canvas.docx ├── 5_6298785061042914214.PDF ├── AEIOU_Summary_Team_No.docx ├── Business model canvas.PNG ├── Final Project Report.pdf ├── AEIOU_Summary_Team_No(1).docx ├── Final Project Report(1)(1).docx ├── Final Project Report-final.docx ├── Final Project Report-final.pdf ├── Empathy Mapping canvas FINAL.docx ├── product development canvas FINAL.docx └── patent1.txt ├── models ├── model.bin ├── model_city.bin ├── model_city1.bin ├── model_city2.bin ├── model_city3.bin ├── model_city1_2.bin └── model_city1_3.bin ├── maps_images ├── city2.JPG ├── city3.JPG ├── Capture.JPG ├── citymap.JPG └── ezgif.com-gif-maker.gif.mp4 ├── arduino_images ├── arduino1.jpg ├── arduino2.jpg └── arduino3.jpg ├── maps ├── nodes.nod.xml ├── edges.edg.xml ├── tripinfo.xml ├── routes3.rou.xml ├── routes3.rou.alt.xml ├── outputs.out ├── city2.rou.xml ├── network.net.xml ├── city3.rou.xml ├── city2.rou.alt.xml ├── randomTrips.py └── trips.trips.xml ├── configuration.sumocfg ├── trafficlight_2 └── trafficlight_2.ino ├── README.md └── train.py /plots/hellooo.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | documentation/ 2 | arduino_images/ 3 | maps_images/ 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | torch 2 | numpy 3 | matplotlib 4 | sumo 5 | -------------------------------------------------------------------------------- /documentation/project_info.txt: -------------------------------------------------------------------------------- 1 | traffic light management system info. 2 | -------------------------------------------------------------------------------- /models/model.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/models/model.bin -------------------------------------------------------------------------------- /maps_images/city2.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/maps_images/city2.JPG -------------------------------------------------------------------------------- /maps_images/city3.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/maps_images/city3.JPG -------------------------------------------------------------------------------- /models/model_city.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/models/model_city.bin -------------------------------------------------------------------------------- /models/model_city1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/models/model_city1.bin -------------------------------------------------------------------------------- /models/model_city2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/models/model_city2.bin -------------------------------------------------------------------------------- /models/model_city3.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/models/model_city3.bin -------------------------------------------------------------------------------- /documentation/PSAR4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/PSAR4.pdf -------------------------------------------------------------------------------- /documentation/patent1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/patent1.pdf -------------------------------------------------------------------------------- /documentation/patent2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/patent2.pdf -------------------------------------------------------------------------------- /documentation/psar3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/psar3.pdf -------------------------------------------------------------------------------- /documentation/psar5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/psar5.pdf -------------------------------------------------------------------------------- /maps_images/Capture.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/maps_images/Capture.JPG -------------------------------------------------------------------------------- /maps_images/citymap.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/maps_images/citymap.JPG -------------------------------------------------------------------------------- /models/model_city1_2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/models/model_city1_2.bin -------------------------------------------------------------------------------- /models/model_city1_3.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/models/model_city1_3.bin -------------------------------------------------------------------------------- /arduino_images/arduino1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/arduino_images/arduino1.jpg -------------------------------------------------------------------------------- /arduino_images/arduino2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/arduino_images/arduino2.jpg -------------------------------------------------------------------------------- /arduino_images/arduino3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/arduino_images/arduino3.jpg -------------------------------------------------------------------------------- /documentation/PSAR2(1).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/PSAR2(1).pdf -------------------------------------------------------------------------------- /documentation/test_loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/test_loop.png -------------------------------------------------------------------------------- /documentation/samplecity1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/samplecity1.PNG -------------------------------------------------------------------------------- /documentation/train_loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/train_loop.png -------------------------------------------------------------------------------- /plots/time_vs_epoch_city1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/plots/time_vs_epoch_city1.png -------------------------------------------------------------------------------- /plots/time_vs_epoch_city3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/plots/time_vs_epoch_city3.png -------------------------------------------------------------------------------- /plots/time_vs_epoch_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/plots/time_vs_epoch_model.png -------------------------------------------------------------------------------- /documentation/Ideation canvas.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/Ideation canvas.docx -------------------------------------------------------------------------------- /documentation/5_6298785061042914214.PDF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/5_6298785061042914214.PDF -------------------------------------------------------------------------------- /documentation/AEIOU_Summary_Team_No.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/AEIOU_Summary_Team_No.docx -------------------------------------------------------------------------------- /documentation/Business model canvas.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/Business model canvas.PNG -------------------------------------------------------------------------------- /documentation/Final Project Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/Final Project Report.pdf -------------------------------------------------------------------------------- /maps_images/ezgif.com-gif-maker.gif.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/maps_images/ezgif.com-gif-maker.gif.mp4 -------------------------------------------------------------------------------- /documentation/AEIOU_Summary_Team_No(1).docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/AEIOU_Summary_Team_No(1).docx -------------------------------------------------------------------------------- /documentation/Final Project Report(1)(1).docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/Final Project Report(1)(1).docx -------------------------------------------------------------------------------- /documentation/Final Project Report-final.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/Final Project Report-final.docx -------------------------------------------------------------------------------- /documentation/Final Project Report-final.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/Final Project Report-final.pdf -------------------------------------------------------------------------------- /documentation/Empathy Mapping canvas FINAL.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/Empathy Mapping canvas FINAL.docx -------------------------------------------------------------------------------- /documentation/product development canvas FINAL.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maunish-dave/Dynamic-Traffic-light-management-system/HEAD/documentation/product development canvas FINAL.docx -------------------------------------------------------------------------------- /maps/nodes.nod.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /maps/edges.edg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /configuration.sumocfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /maps/tripinfo.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /trafficlight_2/trafficlight_2.ino: -------------------------------------------------------------------------------- 1 | int pin13 = 13; 2 | int pin12 = 12; 3 | int pin11 = 11; 4 | 5 | int pin10 = 10; 6 | int pin9 = 9; 7 | int pin8 = 8; 8 | 9 | int pin7 = 7; 10 | int pin6 = 6; 11 | int pin5 = 5; 12 | 13 | int pin4 = 4; 14 | int pin3 = 3; 15 | int pin2 = 2; 16 | 17 | int phase; 18 | int x; 19 | void setup() { 20 | pinMode(pin13, OUTPUT); 21 | pinMode(pin12, OUTPUT); 22 | pinMode(pin11, OUTPUT); 23 | pinMode(pin10, OUTPUT); 24 | pinMode(pin9, OUTPUT); 25 | pinMode(pin8, OUTPUT); 26 | pinMode(pin7, OUTPUT); 27 | pinMode(pin6, OUTPUT); 28 | pinMode(pin5, OUTPUT); 29 | pinMode(pin4, OUTPUT); 30 | pinMode(pin3, OUTPUT); 31 | pinMode(pin2, OUTPUT); 32 | 33 | Serial.begin(9600); 34 | Serial.setTimeout(1); 35 | 36 | } 37 | 38 | void loop() { 39 | while (!Serial.available()); 40 | phase = Serial.readString().toInt(); 41 | Serial.print(phase + 1); 42 | 43 | 44 | if (phase == 0){ 45 | digitalWrite(pin13, HIGH); 46 | digitalWrite(pin10, HIGH); 47 | digitalWrite(pin7, HIGH); 48 | digitalWrite(pin2, HIGH); 49 | 50 | digitalWrite(pin11, LOW); 51 | digitalWrite(pin12, LOW); 52 | digitalWrite(pin9, LOW); 53 | digitalWrite(pin8, LOW); 54 | digitalWrite(pin6, LOW); 55 | digitalWrite(pin5, LOW); 56 | digitalWrite(pin3, LOW); 57 | digitalWrite(pin4, LOW); 58 | } 59 | 60 | if (phase == 2){ 61 | digitalWrite(pin13, HIGH); 62 | digitalWrite(pin10, HIGH); 63 | digitalWrite(pin5, HIGH); 64 | digitalWrite(pin4, HIGH); 65 | 66 | digitalWrite(pin11, LOW); 67 | digitalWrite(pin12, LOW); 68 | digitalWrite(pin9, LOW); 69 | digitalWrite(pin8, LOW); 70 | digitalWrite(pin6, LOW); 71 | digitalWrite(pin7, LOW); 72 | digitalWrite(pin3, LOW); 73 | digitalWrite(pin2, LOW); 74 | } 75 | 76 | if (phase == 4){ 77 | digitalWrite(pin11, HIGH); 78 | digitalWrite(pin10, HIGH); 79 | digitalWrite(pin7, HIGH); 80 | digitalWrite(pin4, HIGH); 81 | 82 | digitalWrite(pin13, LOW); 83 | digitalWrite(pin12, LOW); 84 | digitalWrite(pin9, LOW); 85 | digitalWrite(pin8, LOW); 86 | digitalWrite(pin6, LOW); 87 | digitalWrite(pin5, LOW); 88 | digitalWrite(pin3, LOW); 89 | digitalWrite(pin2, LOW); 90 | } 91 | 92 | if (phase == 6){ 93 | digitalWrite(pin13, HIGH); 94 | digitalWrite(pin8, HIGH); 95 | digitalWrite(pin7, HIGH); 96 | digitalWrite(pin4, HIGH); 97 | 98 | digitalWrite(pin11, LOW); 99 | digitalWrite(pin12, LOW); 100 | digitalWrite(pin9, LOW); 101 | digitalWrite(pin10, LOW); 102 | digitalWrite(pin6, LOW); 103 | digitalWrite(pin5, LOW); 104 | digitalWrite(pin3, LOW); 105 | digitalWrite(pin2, LOW); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /documentation/patent1.txt: -------------------------------------------------------------------------------- 1 | Google Patents 2 | 3 | keywords: 4 | traffic , prediction , system 5 | 6 | search string: traffic lights prediction system 7 | 8 | number of results : 5 9 | ---------------------------- 10 | Environmental Science And Engineering 11 | 12 | Controlling traffic signals 13 | 14 | Ipc : G08G1/07 15 | 16 | Title: Traffic light prediction system 17 | 18 | Patent No. US 7,187,301 B2 19 | 20 | App No. 10/894,922 21 | 22 | weblink: https://patents.google.com/patent/US7187301B2/en?oq=traffic+lights#title 23 | 24 | Date of filing: 2004-07-20 25 | 26 | Name of Inventor: Guixian Lu 27 | 28 | Address of Inventor: Melrose Rd Pontiac MI US 48340 29 | 30 | Name of Applicant/Assignee: Guixian Lu 31 | 32 | Name of Applicant/Assignee: Melrose Rd Pontiac MI US 48340 33 | 34 | Application for patent is: individual 35 | 36 | ---------------------------------- 37 | 38 | Limitation:The limitation to current technology is it only gives driver of the vehicle the information regarding the future traffic lights. 39 | but the system won't optimize itself and adapt to current traffic situation to reduce the traffic. 40 | Another limitation is to setup various different lights for different moving section which is not cost effective. 41 | 42 | 43 | 44 | Specific Problem solved by invention:primary objective of the present invention is to save fuel. 45 | other objective are to save fuel to maximize the usage of streets, 46 | and to reduce traffic accidents. 47 | 48 | 49 | Brief about invention:A traffic system that helps a driver to save gasoline by avoiding red light or by decelerating before a red light. It predicts the colors of a traffic light and informs about the future traffic light colors that will happen to a driver. The system comprising a sub-control system, three kinds of moving sections representing three future colors: green, yellow, and red. The positions of the moving sections are showed by indicators. The indicators are secured along one side of the street. 50 | 51 | 52 | 53 | Key learning points:The idea here is creative but the cost required to make this is not proportional to the cost it saves. 54 | 55 | 56 | Summary of invention:The primary objective of the present invention is to save fuel for vehicles and travel time. Other objectives are to reduce pollution from vehicles, to maximize the usage of the streets, and to reduce traffic accidents and traffic jams. 57 | 58 | The forgoing objectives are accomplished by defining moving sections on a street, moving towards the traffic light. Usually each kind of moving section represents one future color from the traffic light. Green sections will result in arriving to a green light. Red section will result in arriving to a red light. There are Indicators informing the drivers about the locations and colors of the moving sections. Some small lights, may act as Indicators. The drivers will know how to change the speed in order to shift from a red section to a green section. 59 | 60 | 61 | 62 | Number of claims:10 63 | 64 | 65 | Patent status:expired 66 | 67 | 68 | How much this invention is related with your IDP/UDP? 69 | 70 | Instead of using lights as indicator for the future traffic lights there should be a system which can broadcast signal directly to system in your car or phone. which will make this cost effective. Other than that it would be better if the system adapts to current traffic condition to reduce traffic jams and save waiting time on traffic lights. 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /maps/routes3.rou.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dynamic-Traffic-light-management-system 2 | This repository contains files for the traffic light management system using Reinforcement Learning. 3 | 4 | ## Basic Idea 5 | 6 | ![sample](documentation/samplecity1.PNG) 7 | 8 | Suppose we have a city grid as shown above with 4 traffic light nodes.
9 | n1, n2, n3, and n4 10 | 11 | So, our model makes 4 decisions (one for each node) for which side to select for the green signal
12 | 13 | we have to select a minimum time (for ex 30s) that our model can not select a green light time below that limit. 14 | 15 | Our task is to minimize the amount of time vehicles have to wait on the traffic signal.
16 | The amount of waiting time for a given traffic signal is equal to the total car present on the signal x number of seconds.
17 | Each traffic signal will have 4 waiting time counter for each side of the road. So based on that our model will
18 | decide which side to select for the green signal. 19 | 20 | ![train](documentation/train_loop.png) 21 | 22 | ## Basic training process. 23 | 24 | We have trained our model on a number of events.
25 | Event is defined as a fixed motion where vehicles will pass through nodes in a fixed (pseudo-random manner).
26 | The reason for keeping the event fixed is that using a random event every time will give a random result.
27 | we will use many such fixed events to train our model so our model can handle different situations. 28 | 29 | The only input our model will receive is the number of vehicles present on 4 sides of each traffic node.
30 | and our model will output 4 sides one for each node. 31 | 32 | The number of nodes depends on the size of the grid. 33 | 34 | ## SUMO for siumlation 35 | 36 | We used SUMO open-source software to make maps and generate simulations to train our model. 37 | 38 | Here are examples of some of the maps used to train the model. 39 | 40 | ### Map1 41 | ![map1](maps_images/city2.JPG) 42 | 43 | ### Map2 44 | ![map2](maps_images/city3.JPG) 45 | 46 | ### Map 3 47 | ![map3](maps_images/citymap.JPG) 48 | 49 | ### Epoch Vs Time for Map1 50 | 51 | ![evst](plots/time_vs_epoch_city1.png) 52 | 53 | ### Epoch Vs Time for Map2 54 | ![evst2](plots/time_vs_epoch_city3.png) 55 | 56 | ### Epoch Vs Time for Map3 57 | ![evst3](plots/time_vs_epoch_model.png) 58 | 59 | ## Simulation of Trained Model. 60 | 61 | 62 | 63 | https://user-images.githubusercontent.com/44360315/113673665-e8edd300-96d6-11eb-8fbe-d09e078fbfbe.mp4 64 | 65 | 66 | 67 | ## Arduino connection. 68 | 69 | We have connected our simulation with Arduino.
70 | 71 | ### Arduino1 72 | 73 | 74 | ### Arduino2 75 | 76 | 77 | ### Arduino3 78 | 79 | 80 | ## How to train new Networks. 81 | 82 | First Download or clone the repository.
83 | Then pip install requirements.txt using 84 | 85 | `pip install -r requirements.txt` 86 | 87 | you need to download SUMO GUI for running simulations. 88 | 89 | download sumo gui from [here](https://sumo.dlr.de/docs/Downloads.php) 90 | 91 | ### Step1: create network and route file 92 | 93 | Use SUMO netedit tool to create a network
94 | for example 'network.net.xml' and save it in the maps folder. 95 | 96 | cd into maps folder and run the following command 97 | 98 | `python randomTrips.py -n network.net.xml -r routes.rou.xml -e 500` 99 | 100 | This will create a routes.rou.xml file for 500 simulation steps for the network "network.net.xml" 101 | 102 | ### Step2: Set Configuration file. 103 | 104 | You need to provide network and route files to the Configuration file.
105 | change net-file and route-files in input. 106 | 107 | `` 108 | `` 109 | `` 110 | `` 111 | 112 | ### Step3: Train the model. 113 | 114 | Now use the train.py file to train a model for this network.
115 | 116 | `python train.py --train -e 50 -m model_name -s 500` 117 | 118 | This code will train the model for 50 epochs.
119 | -e is to set the epochs.
120 | -m for model_name which will be saved in the model folder.
121 | -s tells simulation to run for 500 steps.
122 | --train tells the train.py to train the model if not specified it will load model_name from the model's folder. 123 | 124 | At the end of the simulation, it will show time_vs_epoch graphs and save them to plots folder with name time_vs_epoch_{model_name}.png 125 | 126 | ### Step4: Running trained model. 127 | 128 | You can use train.py to run a pre-trained model on GUI. 129 | 130 | `python train.py -m model_name -s 500` 131 | 132 | This will open GUI which you can run to see how your model performs. 133 | To get accurate results set a value of -s the same for testing and training. 134 | 135 | ### Extra: Running Ardunio 136 | Currently, Arduino works only for a single crossroad.
137 | More than one cross road will return an error.
138 | 139 | For running Arduino for testing use --ard. 140 | 141 | `python train.py -m model_name -s 500 --ard` 142 | -------------------------------------------------------------------------------- /maps/routes3.rou.alt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /maps/outputs.out: -------------------------------------------------------------------------------- 1 | 2 | 3 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /train.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import os 5 | import sys 6 | import time 7 | import optparse 8 | import random 9 | import serial 10 | import numpy as np 11 | import torch 12 | import torch.optim as optim 13 | import torch.nn.functional as F 14 | import torch.nn as nn 15 | import matplotlib.pyplot as plt 16 | 17 | # we need to import python modules from the $SUMO_HOME/tools directory 18 | if "SUMO_HOME" in os.environ: 19 | tools = os.path.join(os.environ["SUMO_HOME"], "tools") 20 | sys.path.append(tools) 21 | else: 22 | sys.exit("please declare environment variable 'SUMO_HOME'") 23 | 24 | from sumolib import checkBinary # noqa 25 | import traci # noqa 26 | 27 | def get_vehicle_numbers(lanes): 28 | vehicle_per_lane = dict() 29 | for l in lanes: 30 | vehicle_per_lane[l] = 0 31 | for k in traci.lane.getLastStepVehicleIDs(l): 32 | if traci.vehicle.getLanePosition(k) > 10: 33 | vehicle_per_lane[l] += 1 34 | return vehicle_per_lane 35 | 36 | 37 | def get_waiting_time(lanes): 38 | waiting_time = 0 39 | for lane in lanes: 40 | waiting_time += traci.lane.getWaitingTime(lane) 41 | return waiting_time 42 | 43 | 44 | def phaseDuration(junction, phase_time, phase_state): 45 | traci.trafficlight.setRedYellowGreenState(junction, phase_state) 46 | traci.trafficlight.setPhaseDuration(junction, phase_time) 47 | 48 | 49 | 50 | class Model(nn.Module): 51 | def __init__(self, lr, input_dims, fc1_dims, fc2_dims, n_actions): 52 | super(Model, self).__init__() 53 | self.lr = lr 54 | self.input_dims = input_dims 55 | self.fc1_dims = fc1_dims 56 | self.fc2_dims = fc2_dims 57 | self.n_actions = n_actions 58 | 59 | self.linear1 = nn.Linear(self.input_dims, self.fc1_dims) 60 | self.linear2 = nn.Linear(self.fc1_dims, self.fc2_dims) 61 | self.linear3 = nn.Linear(self.fc2_dims, self.n_actions) 62 | 63 | self.optimizer = optim.Adam(self.parameters(), lr=self.lr) 64 | self.loss = nn.MSELoss() 65 | self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 66 | self.to(self.device) 67 | 68 | def forward(self, state): 69 | x = F.relu(self.linear1(state)) 70 | x = F.relu(self.linear2(x)) 71 | actions = self.linear3(x) 72 | return actions 73 | 74 | 75 | class Agent: 76 | def __init__( 77 | self, 78 | gamma, 79 | epsilon, 80 | lr, 81 | input_dims, 82 | fc1_dims, 83 | fc2_dims, 84 | batch_size, 85 | n_actions, 86 | junctions, 87 | max_memory_size=100000, 88 | epsilon_dec=5e-4, 89 | epsilon_end=0.05, 90 | ): 91 | self.gamma = gamma 92 | self.epsilon = epsilon 93 | self.lr = lr 94 | self.batch_size = batch_size 95 | self.input_dims = input_dims 96 | self.fc1_dims = fc1_dims 97 | self.fc2_dims = fc2_dims 98 | self.n_actions = n_actions 99 | self.action_space = [i for i in range(n_actions)] 100 | self.junctions = junctions 101 | self.max_mem = max_memory_size 102 | self.epsilon_dec = epsilon_dec 103 | self.epsilon_end = epsilon_end 104 | self.mem_cntr = 0 105 | self.iter_cntr = 0 106 | self.replace_target = 100 107 | 108 | self.Q_eval = Model( 109 | self.lr, self.input_dims, self.fc1_dims, self.fc2_dims, self.n_actions 110 | ) 111 | self.memory = dict() 112 | for junction in junctions: 113 | self.memory[junction] = { 114 | "state_memory": np.zeros( 115 | (self.max_mem, self.input_dims), dtype=np.float32 116 | ), 117 | "new_state_memory": np.zeros( 118 | (self.max_mem, self.input_dims), dtype=np.float32 119 | ), 120 | "reward_memory":np.zeros(self.max_mem, dtype=np.float32), 121 | "action_memory": np.zeros(self.max_mem, dtype=np.int32), 122 | "terminal_memory": np.zeros(self.max_mem, dtype=np.bool), 123 | "mem_cntr": 0, 124 | "iter_cntr": 0, 125 | } 126 | 127 | 128 | def store_transition(self, state, state_, action,reward, done,junction): 129 | index = self.memory[junction]["mem_cntr"] % self.max_mem 130 | self.memory[junction]["state_memory"][index] = state 131 | self.memory[junction]["new_state_memory"][index] = state_ 132 | self.memory[junction]['reward_memory'][index] = reward 133 | self.memory[junction]['terminal_memory'][index] = done 134 | self.memory[junction]["action_memory"][index] = action 135 | self.memory[junction]["mem_cntr"] += 1 136 | 137 | def choose_action(self, observation): 138 | state = torch.tensor([observation], dtype=torch.float).to(self.Q_eval.device) 139 | if np.random.random() > self.epsilon: 140 | actions = self.Q_eval.forward(state) 141 | action = torch.argmax(actions).item() 142 | else: 143 | action = np.random.choice(self.action_space) 144 | return action 145 | 146 | def reset(self,junction_numbers): 147 | for junction_number in junction_numbers: 148 | self.memory[junction_number]['mem_cntr'] = 0 149 | 150 | def save(self,model_name): 151 | torch.save(self.Q_eval.state_dict(),f'models/{model_name}.bin') 152 | 153 | def learn(self, junction): 154 | self.Q_eval.optimizer.zero_grad() 155 | 156 | batch= np.arange(self.memory[junction]['mem_cntr'], dtype=np.int32) 157 | 158 | state_batch = torch.tensor(self.memory[junction]["state_memory"][batch]).to( 159 | self.Q_eval.device 160 | ) 161 | new_state_batch = torch.tensor( 162 | self.memory[junction]["new_state_memory"][batch] 163 | ).to(self.Q_eval.device) 164 | reward_batch = torch.tensor( 165 | self.memory[junction]['reward_memory'][batch]).to(self.Q_eval.device) 166 | terminal_batch = torch.tensor(self.memory[junction]['terminal_memory'][batch]).to(self.Q_eval.device) 167 | action_batch = self.memory[junction]["action_memory"][batch] 168 | 169 | q_eval = self.Q_eval.forward(state_batch)[batch, action_batch] 170 | q_next = self.Q_eval.forward(new_state_batch) 171 | q_next[terminal_batch] = 0.0 172 | q_target = reward_batch + self.gamma * torch.max(q_next, dim=1)[0] 173 | loss = self.Q_eval.loss(q_target, q_eval).to(self.Q_eval.device) 174 | 175 | loss.backward() 176 | self.Q_eval.optimizer.step() 177 | 178 | self.iter_cntr += 1 179 | self.epsilon = ( 180 | self.epsilon - self.epsilon_dec 181 | if self.epsilon > self.epsilon_end 182 | else self.epsilon_end 183 | ) 184 | 185 | 186 | def run(train=True,model_name="model",epochs=50,steps=500,ard=False): 187 | if ard: 188 | arduino = serial.Serial(port='COM4', baudrate=9600, timeout=.1) 189 | def write_read(x): 190 | arduino.write(bytes(x, 'utf-8')) 191 | time.sleep(0.05) 192 | data = arduino.readline() 193 | return data 194 | """execute the TraCI control loop""" 195 | epochs = epochs 196 | steps = steps 197 | best_time = np.inf 198 | total_time_list = list() 199 | traci.start( 200 | [checkBinary("sumo"), "-c", "configuration.sumocfg", "--tripinfo-output", "maps/tripinfo.xml"] 201 | ) 202 | all_junctions = traci.trafficlight.getIDList() 203 | junction_numbers = list(range(len(all_junctions))) 204 | 205 | brain = Agent( 206 | gamma=0.99, 207 | epsilon=0.0, 208 | lr=0.1, 209 | input_dims=4, 210 | # input_dims = len(all_junctions) * 4, 211 | fc1_dims=256, 212 | fc2_dims=256, 213 | batch_size=1024, 214 | n_actions=4, 215 | junctions=junction_numbers, 216 | ) 217 | 218 | if not train: 219 | brain.Q_eval.load_state_dict(torch.load(f'models/{model_name}.bin',map_location=brain.Q_eval.device)) 220 | 221 | print(brain.Q_eval.device) 222 | traci.close() 223 | for e in range(epochs): 224 | if train: 225 | traci.start( 226 | [checkBinary("sumo"), "-c", "configuration.sumocfg", "--tripinfo-output", "tripinfo.xml"] 227 | ) 228 | else: 229 | traci.start( 230 | [checkBinary("sumo-gui"), "-c", "configuration.sumocfg", "--tripinfo-output", "tripinfo.xml"] 231 | ) 232 | 233 | print(f"epoch: {e}") 234 | select_lane = [ 235 | ["yyyrrrrrrrrr", "GGGrrrrrrrrr"], 236 | ["rrryyyrrrrrr", "rrrGGGrrrrrr"], 237 | ["rrrrrryyyrrr", "rrrrrrGGGrrr"], 238 | ["rrrrrrrrryyy", "rrrrrrrrrGGG"], 239 | ] 240 | 241 | # select_lane = [ 242 | # ["yyyyrrrrrrrrrrrr", "GGGGrrrrrrrrrrrr"], 243 | # ["rrrryyyyrrrrrrrr", "rrrrGGGGrrrrrrrr"], 244 | # ["rrrrrrrryyyyrrrr", "rrrrrrrrGGGGrrrr"], 245 | # ["rrrrrrrrrrrryyyy", "rrrrrrrrrrrrGGGG"], 246 | # ] 247 | 248 | step = 0 249 | total_time = 0 250 | min_duration = 5 251 | 252 | traffic_lights_time = dict() 253 | prev_wait_time = dict() 254 | prev_vehicles_per_lane = dict() 255 | prev_action = dict() 256 | all_lanes = list() 257 | 258 | for junction_number, junction in enumerate(all_junctions): 259 | prev_wait_time[junction] = 0 260 | prev_action[junction_number] = 0 261 | traffic_lights_time[junction] = 0 262 | prev_vehicles_per_lane[junction_number] = [0] * 4 263 | # prev_vehicles_per_lane[junction_number] = [0] * (len(all_junctions) * 4) 264 | all_lanes.extend(list(traci.trafficlight.getControlledLanes(junction))) 265 | 266 | while step <= steps: 267 | traci.simulationStep() 268 | for junction_number, junction in enumerate(all_junctions): 269 | controled_lanes = traci.trafficlight.getControlledLanes(junction) 270 | waiting_time = get_waiting_time(controled_lanes) 271 | total_time += waiting_time 272 | if traffic_lights_time[junction] == 0: 273 | vehicles_per_lane = get_vehicle_numbers(controled_lanes) 274 | # vehicles_per_lane = get_vehicle_numbers(all_lanes) 275 | 276 | #storing previous state and current state 277 | reward = -1 * waiting_time 278 | state_ = list(vehicles_per_lane.values()) 279 | state = prev_vehicles_per_lane[junction_number] 280 | prev_vehicles_per_lane[junction_number] = state_ 281 | brain.store_transition(state, state_, prev_action[junction_number],reward,(step==steps),junction_number) 282 | 283 | #selecting new action based on current state 284 | lane = brain.choose_action(state_) 285 | prev_action[junction_number] = lane 286 | phaseDuration(junction, 6, select_lane[lane][0]) 287 | phaseDuration(junction, min_duration + 10, select_lane[lane][1]) 288 | 289 | if ard: 290 | ph = str(traci.trafficlight.getPhase("0")) 291 | value = write_read(ph) 292 | 293 | traffic_lights_time[junction] = min_duration + 10 294 | if train: 295 | brain.learn(junction_number) 296 | else: 297 | traffic_lights_time[junction] -= 1 298 | step += 1 299 | print("total_time",total_time) 300 | total_time_list.append(total_time) 301 | 302 | if total_time < best_time: 303 | best_time = total_time 304 | if train: 305 | brain.save(model_name) 306 | 307 | traci.close() 308 | sys.stdout.flush() 309 | if not train: 310 | break 311 | if train: 312 | plt.plot(list(range(len(total_time_list))),total_time_list) 313 | plt.xlabel("epochs") 314 | plt.ylabel("total time") 315 | plt.savefig(f'plots/time_vs_epoch_{model_name}.png') 316 | plt.show() 317 | 318 | def get_options(): 319 | optParser = optparse.OptionParser() 320 | optParser.add_option( 321 | "-m", 322 | dest='model_name', 323 | type='string', 324 | default="model", 325 | help="name of model", 326 | ) 327 | optParser.add_option( 328 | "--train", 329 | action = 'store_true', 330 | default=False, 331 | help="training or testing", 332 | ) 333 | optParser.add_option( 334 | "-e", 335 | dest='epochs', 336 | type='int', 337 | default=50, 338 | help="Number of epochs", 339 | ) 340 | optParser.add_option( 341 | "-s", 342 | dest='steps', 343 | type='int', 344 | default=500, 345 | help="Number of steps", 346 | ) 347 | optParser.add_option( 348 | "--ard", 349 | action='store_true', 350 | default=False, 351 | help="Connect Arduino", 352 | ) 353 | options, args = optParser.parse_args() 354 | return options 355 | 356 | 357 | # this is the main entry point of this script 358 | if __name__ == "__main__": 359 | options = get_options() 360 | model_name = options.model_name 361 | train = options.train 362 | epochs = options.epochs 363 | steps = options.steps 364 | ard = options.ard 365 | run(train=train,model_name=model_name,epochs=epochs,steps=steps,ard=ard) 366 | -------------------------------------------------------------------------------- /maps/city2.rou.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | -------------------------------------------------------------------------------- /maps/network.net.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /maps/city3.rou.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | -------------------------------------------------------------------------------- /maps/city2.rou.alt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | -------------------------------------------------------------------------------- /maps/randomTrips.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo 3 | # Copyright (C) 2010-2020 German Aerospace Center (DLR) and others. 4 | # This program and the accompanying materials are made available under the 5 | # terms of the Eclipse Public License 2.0 which is available at 6 | # https://www.eclipse.org/legal/epl-2.0/ 7 | # This Source Code may also be made available under the following Secondary 8 | # Licenses when the conditions for such availability set forth in the Eclipse 9 | # Public License 2.0 are satisfied: GNU General Public License, version 2 10 | # or later which is available at 11 | # https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html 12 | # SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later 13 | 14 | # @file randomTrips.py 15 | # @author Daniel Krajzewicz 16 | # @author Jakob Erdmann 17 | # @author Michael Behrisch 18 | # @date 2010-03-06 19 | 20 | 21 | from __future__ import print_function 22 | from __future__ import absolute_import 23 | import os 24 | import sys 25 | import random 26 | import bisect 27 | import subprocess 28 | from collections import defaultdict 29 | import math 30 | import optparse 31 | 32 | if 'SUMO_HOME' in os.environ: 33 | sys.path.append(os.path.join(os.environ['SUMO_HOME'], 'tools')) 34 | import sumolib # noqa 35 | from sumolib.miscutils import euclidean # noqa 36 | from sumolib.geomhelper import naviDegree, minAngleDegreeDiff # noqa 37 | 38 | DUAROUTER = sumolib.checkBinary('duarouter') 39 | 40 | SOURCE_SUFFIX = ".src.xml" 41 | SINK_SUFFIX = ".dst.xml" 42 | VIA_SUFFIX = ".via.xml" 43 | 44 | 45 | def get_options(args=None): 46 | optParser = optparse.OptionParser() 47 | optParser.add_option("-n", "--net-file", dest="netfile", 48 | help="define the net file (mandatory)") 49 | optParser.add_option("-a", "--additional-files", dest="additional", 50 | help="define additional files to be loaded by the router") 51 | optParser.add_option("-o", "--output-trip-file", dest="tripfile", 52 | default="trips.trips.xml", help="define the output trip filename") 53 | optParser.add_option("-r", "--route-file", dest="routefile", 54 | help="generates route file with duarouter") 55 | optParser.add_option("--vtype-output", dest="vtypeout", 56 | help="Store generated vehicle types in a separate file") 57 | optParser.add_option("--weights-prefix", dest="weightsprefix", 58 | help="loads probabilities for being source, destination and via-edge from the files named " + 59 | ".src.xml, .sink.xml and .via.xml") 60 | optParser.add_option("--weights-output-prefix", dest="weights_outprefix", 61 | help="generates weights files for visualisation") 62 | optParser.add_option("--pedestrians", action="store_true", 63 | default=False, help="create a person file with pedestrian trips instead of vehicle trips") 64 | optParser.add_option("--persontrips", action="store_true", 65 | default=False, help="create a person file with person trips instead of vehicle trips") 66 | optParser.add_option("--personrides", help="create a person file with rides using STR as lines attribute") 67 | optParser.add_option("--persontrip.transfer.car-walk", dest="carWalkMode", 68 | help="Where are mode changes from car to walking allowed " + 69 | "(possible values: 'ptStops', 'allJunctions' and combinations)") 70 | optParser.add_option("--persontrip.walkfactor", dest="walkfactor", 71 | help="Use FLOAT as a factor on pedestrian maximum speed during intermodal routing") 72 | optParser.add_option("--prefix", dest="tripprefix", 73 | default="", help="prefix for the trip ids") 74 | optParser.add_option("-t", "--trip-attributes", dest="tripattrs", 75 | default="", help="additional trip attributes. When generating pedestrians, attributes for " + 76 | " and are supported.") 77 | optParser.add_option("--fringe-start-attributes", dest="fringeattrs", 78 | default="", help="additional trip attributes when starting on a fringe.") 79 | optParser.add_option("-b", "--begin", default=0, help="begin time") 80 | optParser.add_option("-e", "--end", default=3600, help="end time (default 3600)") 81 | optParser.add_option( 82 | "-p", "--period", type="float", default=1, help="Generate vehicles with equidistant departure times and " + 83 | "period=FLOAT (default 1.0). If option --binomial is used, the expected arrival rate is set to 1/period.") 84 | optParser.add_option("-s", "--seed", type="int", default=42, help="random seed") 85 | optParser.add_option("--random", action="store_true", 86 | default=False, help="use a random seed to initialize the random number generator") 87 | optParser.add_option("-l", "--length", action="store_true", 88 | default=False, help="weight edge probability by length") 89 | optParser.add_option("-L", "--lanes", action="store_true", 90 | default=False, help="weight edge probability by number of lanes") 91 | optParser.add_option("--edge-param", dest="edgeParam", 92 | help="use the given edge parameter as factor for edge") 93 | optParser.add_option("--speed-exponent", type="float", dest="speed_exponent", 94 | default=0.0, help="weight edge probability by speed^ (default 0)") 95 | optParser.add_option("--angle", type="float", dest="angle", 96 | default=90.0, help="weight edge probability by angle [0-360] relative to the network center") 97 | optParser.add_option("--angle-factor", type="float", dest="angle_weight", 98 | default=1.0, help="maximum weight factor for angle") 99 | optParser.add_option("--fringe-factor", type="float", dest="fringe_factor", 100 | default=1.0, help="multiply weight of fringe edges by (default 1") 101 | optParser.add_option("--fringe-threshold", type="float", dest="fringe_threshold", 102 | default=0.0, help="only consider edges with speed above as fringe edges (default 0)") 103 | optParser.add_option("--allow-fringe", dest="allow_fringe", action="store_true", 104 | default=False, help="Allow departing on edges that leave the network and arriving on edges " + 105 | "that enter the network (via turnarounds or as 1-edge trips") 106 | optParser.add_option("--allow-fringe.min-length", type="float", dest="allow_fringe_min_length", 107 | help="Allow departing on edges that leave the network and arriving on edges " + 108 | "that enter the network, if they have at least the given length") 109 | optParser.add_option("--min-distance", type="float", dest="min_distance", 110 | default=0.0, help="require start and end edges for each trip to be at least m apart") 111 | optParser.add_option("--max-distance", type="float", dest="max_distance", 112 | default=None, help="require start and end edges for each trip to be at most m " + 113 | "apart (default 0 which disables any checks)") 114 | optParser.add_option("-i", "--intermediate", type="int", 115 | default=0, help="generates the given number of intermediate way points") 116 | optParser.add_option("--flows", type="int", 117 | default=0, help="generates INT flows that together output vehicles with the specified period") 118 | optParser.add_option("--jtrrouter", action="store_true", 119 | default=False, help="Create flows without destination as input for jtrrouter") 120 | optParser.add_option("--maxtries", type="int", 121 | default=100, help="number of attemps for finding a trip which meets the distance constraints") 122 | optParser.add_option("--binomial", type="int", metavar="N", 123 | help="If this is set, the number of departures per seconds will be drawn from a binomial " + 124 | "distribution with n=N and p=PERIOD/N where PERIOD is the argument given to " + 125 | "option --period. Tnumber of attemps for finding a trip which meets the distance constraints") 126 | optParser.add_option( 127 | "-c", "--vclass", "--edge-permission", default="passenger", 128 | help="only from and to edges which permit the given vehicle class") 129 | optParser.add_option( 130 | "--vehicle-class", help="The vehicle class assigned to the generated trips (adds a standard vType definition " + 131 | "to the output file).") 132 | optParser.add_option("--remove-loops", dest="remove_loops", action="store_true", 133 | default=False, help="Remove loops at route start and end") 134 | optParser.add_option("--junction-taz", dest="junctionTaz", action="store_true", 135 | default=False, help="Write trips with fromJunction and toJunction") 136 | optParser.add_option("--via-edge-types", dest="viaEdgeTypes", 137 | help="Set list of edge types that cannot be used for departure or arrival " + 138 | "(unless being on the fringe)") 139 | optParser.add_option("--validate", default=False, action="store_true", 140 | help="Whether to produce trip output that is already checked for connectivity") 141 | optParser.add_option("-v", "--verbose", action="store_true", 142 | default=False, help="tell me what you are doing") 143 | (options, args) = optParser.parse_args(args=args) 144 | if not options.netfile: 145 | optParser.print_help() 146 | sys.exit(1) 147 | 148 | if options.persontrips or options.personrides: 149 | options.pedestrians = True 150 | 151 | if options.pedestrians: 152 | options.vclass = 'pedestrian' 153 | if options.flows > 0: 154 | print("Error: Person flows are not supported yet", file=sys.stderr) 155 | sys.exit(1) 156 | 157 | if options.validate and options.routefile is None: 158 | options.routefile = "routes.rou.xml" 159 | 160 | if options.period <= 0: 161 | print("Error: Period must be positive", file=sys.stderr) 162 | sys.exit(1) 163 | 164 | if options.jtrrouter and options.flows <= 0: 165 | print("Error: Option --jtrrouter must be used with option --flows", file=sys.stderr) 166 | sys.exit(1) 167 | 168 | if options.vehicle_class: 169 | if options.tripprefix: 170 | options.vtypeID = "%s_%s" % (options.tripprefix, options.vehicle_class) 171 | else: 172 | options.vtypeID = options.vehicle_class 173 | 174 | if 'type=' in options.tripattrs: 175 | print("Error: trip-attribute 'type' cannot be used together with option --vehicle-class", file=sys.stderr) 176 | sys.exit(1) 177 | 178 | if options.viaEdgeTypes: 179 | options.viaEdgeTypes = options.viaEdgeTypes.split(',') 180 | 181 | return options 182 | 183 | 184 | class InvalidGenerator(Exception): 185 | pass 186 | 187 | # assigns a weight to each edge using weight_fun and then draws from a discrete 188 | # distribution with these weights 189 | 190 | 191 | class RandomEdgeGenerator: 192 | 193 | def __init__(self, net, weight_fun): 194 | self.net = net 195 | self.weight_fun = weight_fun 196 | self.cumulative_weights = [] 197 | self.total_weight = 0 198 | for edge in self.net._edges: 199 | # print edge.getID(), weight_fun(edge) 200 | self.total_weight += weight_fun(edge) 201 | self.cumulative_weights.append(self.total_weight) 202 | if self.total_weight == 0: 203 | raise InvalidGenerator() 204 | 205 | def get(self): 206 | r = random.random() * self.total_weight 207 | index = bisect.bisect(self.cumulative_weights, r) 208 | return self.net._edges[index] 209 | 210 | def write_weights(self, fname, interval_id, begin, end): 211 | # normalize to [0,100] 212 | normalizer = 100.0 / max(1, max(map(self.weight_fun, self.net._edges))) 213 | weights = [(self.weight_fun(e) * normalizer, e.getID()) for e in self.net.getEdges()] 214 | weights.sort(reverse=True) 215 | with open(fname, 'w+') as f: 216 | f.write('\n') 217 | f.write(' \n' % ( 218 | interval_id, begin, end)) 219 | for weight, edgeID in weights: 220 | f.write(' \n' % 221 | (edgeID, weight)) 222 | f.write(' \n') 223 | f.write('\n') 224 | 225 | 226 | class RandomTripGenerator: 227 | 228 | def __init__(self, source_generator, sink_generator, via_generator, intermediate, pedestrians): 229 | self.source_generator = source_generator 230 | self.sink_generator = sink_generator 231 | self.via_generator = via_generator 232 | self.intermediate = intermediate 233 | self.pedestrians = pedestrians 234 | 235 | def get_trip(self, min_distance, max_distance, maxtries=100, junctionTaz=False): 236 | for _ in range(maxtries): 237 | source_edge = self.source_generator.get() 238 | intermediate = [self.via_generator.get() 239 | for i in range(self.intermediate)] 240 | sink_edge = self.sink_generator.get() 241 | if self.pedestrians: 242 | destCoord = sink_edge.getFromNode().getCoord() 243 | else: 244 | destCoord = sink_edge.getToNode().getCoord() 245 | 246 | coords = ([source_edge.getFromNode().getCoord()] + 247 | [e.getFromNode().getCoord() for e in intermediate] + 248 | [destCoord]) 249 | distance = sum([euclidean(p, q) 250 | for p, q in zip(coords[:-1], coords[1:])]) 251 | if (distance >= min_distance 252 | and (not junctionTaz or source_edge.getFromNode() != sink_edge.getToNode()) 253 | and (max_distance is None or distance < max_distance)): 254 | return source_edge, sink_edge, intermediate 255 | raise Exception("no trip found after %s tries" % maxtries) 256 | 257 | 258 | def get_prob_fun(options, fringe_bonus, fringe_forbidden, max_length): 259 | # fringe_bonus None generates intermediate way points 260 | def edge_probability(edge): 261 | if options.vclass and not edge.allows(options.vclass): 262 | return 0 # not allowed 263 | if fringe_bonus is None and edge.is_fringe() and not options.pedestrians: 264 | return 0 # not suitable as intermediate way point 265 | if (fringe_forbidden is not None and edge.is_fringe(getattr(edge, fringe_forbidden)) and 266 | not options.pedestrians and 267 | (options.allow_fringe_min_length is None or edge.getLength() < options.allow_fringe_min_length)): 268 | return 0 # the wrong kind of fringe 269 | if (fringe_bonus is not None and options.viaEdgeTypes is not None and not edge.is_fringe() and 270 | edge.getType() in options.viaEdgeTypes): 271 | return 0 # the wrong type of edge (only allows depart and arrival on the fringe) 272 | prob = 1 273 | if options.length: 274 | if options.fringe_factor != 1.0 and fringe_bonus is not None and edge.is_fringe(): 275 | # short fringe edges should not suffer a penalty 276 | prob *= max_length 277 | else: 278 | prob *= edge.getLength() 279 | if options.lanes: 280 | prob *= edge.getLaneNumber() 281 | prob *= (edge.getSpeed() ** options.speed_exponent) 282 | if (options.fringe_factor != 1.0 and 283 | not options.pedestrians and 284 | fringe_bonus is not None and 285 | edge.getSpeed() > options.fringe_threshold and 286 | edge.is_fringe(getattr(edge, fringe_bonus))): 287 | prob *= options.fringe_factor 288 | if options.edgeParam is not None: 289 | prob *= float(edge.getParam(options.edgeParam, 1.0)) 290 | if options.angle_weight != 1.0 and fringe_bonus is not None: 291 | xmin, ymin, xmax, ymax = edge.getBoundingBox() 292 | ex, ey = ((xmin + xmax) / 2, (ymin + ymax) / 2) 293 | nx, ny = options.angle_center 294 | edgeAngle = naviDegree(math.atan2(ey - ny, ex - nx)) 295 | angleDiff = minAngleDegreeDiff(options.angle, edgeAngle) 296 | # print("e=%s nc=%s ec=%s ea=%s a=%s ad=%s" % ( 297 | # edge.getID(), options.angle_center, (ex,ey), edgeAngle, 298 | # options.angle, angleDiff)) 299 | # relDist = 2 * euclidean((ex, ey), options.angle_center) / max(xmax - xmin, ymax - ymin) 300 | # prob *= (relDist * (options.angle_weight - 1) + 1) 301 | if fringe_bonus == "_incoming": 302 | # source edge 303 | prob *= (angleDiff * (options.angle_weight - 1) + 1) 304 | else: 305 | prob *= ((180 - angleDiff) * (options.angle_weight - 1) + 1) 306 | 307 | return prob 308 | return edge_probability 309 | 310 | 311 | class LoadedProps: 312 | 313 | def __init__(self, fname): 314 | self.weights = defaultdict(lambda: 0) 315 | for edge in sumolib.output.parse_fast(fname, 'edge', ['id', 'value']): 316 | self.weights[edge.id] = float(edge.value) 317 | 318 | def __call__(self, edge): 319 | return self.weights[edge.getID()] 320 | 321 | 322 | def buildTripGenerator(net, options): 323 | try: 324 | max_length = 0 325 | for edge in net.getEdges(): 326 | if not edge.is_fringe(): 327 | max_length = max(max_length, edge.getLength()) 328 | forbidden_source_fringe = None if options.allow_fringe else "_outgoing" 329 | forbidden_sink_fringe = None if options.allow_fringe else "_incoming" 330 | source_generator = RandomEdgeGenerator( 331 | net, get_prob_fun(options, "_incoming", forbidden_source_fringe, max_length)) 332 | sink_generator = RandomEdgeGenerator( 333 | net, get_prob_fun(options, "_outgoing", forbidden_sink_fringe, max_length)) 334 | if options.weightsprefix: 335 | if os.path.isfile(options.weightsprefix + SOURCE_SUFFIX): 336 | source_generator = RandomEdgeGenerator( 337 | net, LoadedProps(options.weightsprefix + SOURCE_SUFFIX)) 338 | if os.path.isfile(options.weightsprefix + SINK_SUFFIX): 339 | sink_generator = RandomEdgeGenerator( 340 | net, LoadedProps(options.weightsprefix + SINK_SUFFIX)) 341 | except InvalidGenerator: 342 | print("Error: no valid edges for generating source or destination. Try using option --allow-fringe", 343 | file=sys.stderr) 344 | return None 345 | 346 | try: 347 | via_generator = RandomEdgeGenerator( 348 | net, get_prob_fun(options, None, None, 1)) 349 | if options.weightsprefix and os.path.isfile(options.weightsprefix + VIA_SUFFIX): 350 | via_generator = RandomEdgeGenerator( 351 | net, LoadedProps(options.weightsprefix + VIA_SUFFIX)) 352 | except InvalidGenerator: 353 | if options.intermediate > 0: 354 | print( 355 | "Error: no valid edges for generating intermediate points", file=sys.stderr) 356 | return None 357 | else: 358 | via_generator = None 359 | 360 | return RandomTripGenerator( 361 | source_generator, sink_generator, via_generator, options.intermediate, options.pedestrians) 362 | 363 | 364 | def is_walk_attribute(attr): 365 | for cand in ['arrivalPos', 'speed=', 'duration=', 'busStop=']: 366 | if cand in attr: 367 | return True 368 | return False 369 | 370 | 371 | def is_persontrip_attribute(attr): 372 | for cand in ['vTypes', 'modes']: 373 | if cand in attr: 374 | return True 375 | return False 376 | 377 | 378 | def is_person_attribute(attr): 379 | for cand in ['departPos', 'type']: 380 | if cand in attr: 381 | return True 382 | return False 383 | 384 | 385 | def is_vehicle_attribute(attr): 386 | for cand in ['depart', 'arrival', 'line', 'Number', 'type']: 387 | if cand in attr: 388 | return True 389 | return False 390 | 391 | 392 | def split_trip_attributes(tripattrs, pedestrians, hasType): 393 | # handle attribute values with a space 394 | # assume that no attribute value includes an '=' sign 395 | allattrs = [] 396 | for a in tripattrs.split(): 397 | if "=" in a: 398 | allattrs.append(a) 399 | else: 400 | if len(allattrs) == 0: 401 | print("Warning: invalid trip-attribute '%s'" % a) 402 | else: 403 | allattrs[-1] += ' ' + a 404 | 405 | # figure out which of the tripattrs belong to the or , 406 | # which belong to the and which belong to the or 407 | vehicleattrs = [] 408 | personattrs = [] 409 | vtypeattrs = [] 410 | otherattrs = [] 411 | for a in allattrs: 412 | if pedestrians: 413 | if is_walk_attribute(a) or is_persontrip_attribute(a): 414 | otherattrs.append(a) 415 | elif is_person_attribute(a): 416 | personattrs.append(a) 417 | else: 418 | vtypeattrs.append(a) 419 | else: 420 | if is_vehicle_attribute(a): 421 | vehicleattrs.append(a) 422 | else: 423 | vtypeattrs.append(a) 424 | 425 | if not hasType: 426 | if pedestrians: 427 | personattrs += vtypeattrs 428 | else: 429 | vehicleattrs += vtypeattrs 430 | vtypeattrs = [] 431 | 432 | return (prependSpace(' '.join(vtypeattrs)), 433 | prependSpace(' '.join(vehicleattrs)), 434 | prependSpace(' '.join(personattrs)), 435 | prependSpace(' '.join(otherattrs))) 436 | 437 | 438 | def prependSpace(s): 439 | if len(s) == 0 or s[0] == " ": 440 | return s 441 | else: 442 | return " " + s 443 | 444 | 445 | def main(options): 446 | if not options.random: 447 | random.seed(options.seed) 448 | 449 | net = sumolib.net.readNet(options.netfile) 450 | if options.min_distance > net.getBBoxDiameter() * (options.intermediate + 1): 451 | options.intermediate = int( 452 | math.ceil(options.min_distance / net.getBBoxDiameter())) - 1 453 | print(("Warning: setting number of intermediate waypoints to %s to achieve a minimum trip length of " + 454 | "%s in a network with diameter %.2f.") % ( 455 | options.intermediate, options.min_distance, net.getBBoxDiameter())) 456 | 457 | if options.angle_weight != 1: 458 | xmin, ymin, xmax, ymax = net.getBoundary() 459 | options.angle_center = (xmin + xmax) / 2, (ymin + ymax) / 2 460 | 461 | trip_generator = buildTripGenerator(net, options) 462 | idx = 0 463 | 464 | vtypeattrs, options.tripattrs, personattrs, otherattrs = split_trip_attributes( 465 | options.tripattrs, options.pedestrians, options.vehicle_class) 466 | 467 | vias = {} 468 | 469 | def generate_one(idx): 470 | label = "%s%s" % (options.tripprefix, idx) 471 | try: 472 | source_edge, sink_edge, intermediate = trip_generator.get_trip( 473 | options.min_distance, options.max_distance, options.maxtries, 474 | options.junctionTaz) 475 | combined_attrs = options.tripattrs 476 | if options.fringeattrs and source_edge.is_fringe(source_edge._incoming): 477 | combined_attrs += " " + options.fringeattrs 478 | if options.junctionTaz: 479 | attrFrom = ' fromJunction="%s"' % source_edge.getFromNode().getID() 480 | attrTo = ' toJunction="%s"' % sink_edge.getToNode().getID() 481 | else: 482 | attrFrom = ' from="%s"' % source_edge.getID() 483 | attrTo = ' to="%s"' % sink_edge.getID() 484 | via = "" 485 | if len(intermediate) > 0: 486 | via = ' via="%s" ' % ' '.join( 487 | [e.getID() for e in intermediate]) 488 | if options.validate: 489 | vias[label] = via 490 | if options.pedestrians: 491 | fouttrips.write( 492 | ' \n' % (label, depart, personattrs)) 493 | if options.persontrips: 494 | fouttrips.write( 495 | ' \n' % (attrFrom, attrTo, otherattrs)) 496 | elif options.personrides: 497 | fouttrips.write( 498 | ' \n' % ( 499 | source_edge.getID(), sink_edge.getID(), options.personrides, otherattrs)) 500 | else: 501 | fouttrips.write( 502 | ' \n' % (attrFrom, attrTo, otherattrs)) 503 | fouttrips.write(' \n') 504 | else: 505 | if options.jtrrouter: 506 | attrTo = '' 507 | combined_attrs = attrFrom + attrTo + via + combined_attrs 508 | if options.flows > 0: 509 | if options.binomial: 510 | for j in range(options.binomial): 511 | fouttrips.write((' \n') % ( 512 | label, j, options.begin, options.end, 1.0 / options.period / options.binomial, 513 | combined_attrs)) 514 | else: 515 | fouttrips.write((' \n') % ( 516 | label, options.begin, options.end, options.period * options.flows, combined_attrs)) 517 | else: 518 | fouttrips.write(' \n' % ( 519 | label, depart, combined_attrs)) 520 | except Exception as exc: 521 | print(exc, file=sys.stderr) 522 | return idx + 1 523 | 524 | with open(options.tripfile, 'w') as fouttrips: 525 | sumolib.writeXMLHeader(fouttrips, "$Id$", "routes") # noqa 526 | if options.vehicle_class: 527 | vTypeDef = ' \n' % ( 528 | options.vtypeID, options.vehicle_class, vtypeattrs) 529 | if options.vtypeout: 530 | # ensure that trip output does not contain types, file may be 531 | # overwritten by later call to duarouter 532 | if options.additional is None: 533 | options.additional = options.vtypeout 534 | else: 535 | options.additional += ",options.vtypeout" 536 | with open(options.vtypeout, 'w') as fouttype: 537 | sumolib.writeXMLHeader(fouttype, "$Id$", "additional") # noqa 538 | fouttype.write(vTypeDef) 539 | fouttype.write("\n") 540 | else: 541 | fouttrips.write(vTypeDef) 542 | options.tripattrs += ' type="%s"' % options.vtypeID 543 | personattrs += ' type="%s"' % options.vtypeID 544 | depart = sumolib.miscutils.parseTime(options.begin) 545 | maxTime = sumolib.miscutils.parseTime(options.end) 546 | if trip_generator: 547 | if options.flows == 0: 548 | while depart < maxTime: 549 | if options.binomial is None: 550 | # generate with constant spacing 551 | idx = generate_one(idx) 552 | depart += options.period 553 | else: 554 | # draw n times from a Bernoulli distribution 555 | # for an average arrival rate of 1 / period 556 | prob = 1.0 / options.period / options.binomial 557 | for _ in range(options.binomial): 558 | if random.random() < prob: 559 | idx = generate_one(idx) 560 | depart += 1 561 | else: 562 | for _ in range(options.flows): 563 | idx = generate_one(idx) 564 | 565 | fouttrips.write("\n") 566 | 567 | # call duarouter for routes or validated trips 568 | args = [DUAROUTER, '-n', options.netfile, '-r', options.tripfile, '--ignore-errors', 569 | '--begin', str(options.begin), '--end', str(options.end), '--no-step-log'] 570 | if options.additional is not None: 571 | args += ['--additional-files', options.additional] 572 | if options.carWalkMode is not None: 573 | args += ['--persontrip.transfer.car-walk', options.carWalkMode] 574 | if options.walkfactor is not None: 575 | args += ['--persontrip.walkfactor', options.walkfactor] 576 | if options.remove_loops: 577 | args += ['--remove-loops'] 578 | if options.vtypeout is not None: 579 | args += ['--vtype-output', options.vtypeout] 580 | if options.junctionTaz: 581 | args += ['--junction-taz'] 582 | if not options.verbose: 583 | args += ['--no-warnings'] 584 | else: 585 | args += ['-v'] 586 | 587 | if options.routefile: 588 | args2 = args + ['-o', options.routefile] 589 | print("calling", " ".join(args2)) 590 | sys.stdout.flush() 591 | subprocess.call(args2) 592 | sys.stdout.flush() 593 | 594 | if options.validate: 595 | # write to temporary file because the input is read incrementally 596 | tmpTrips = options.tripfile + ".tmp" 597 | args2 = args + ['-o', tmpTrips, '--write-trips'] 598 | if options.junctionTaz: 599 | args2 += ['--write-trips.junctions'] 600 | print("calling", " ".join(args2)) 601 | sys.stdout.flush() 602 | subprocess.call(args2) 603 | sys.stdout.flush() 604 | os.remove(options.tripfile) # on windows, rename does not overwrite 605 | os.rename(tmpTrips, options.tripfile) 606 | 607 | if options.weights_outprefix: 608 | idPrefix = "" 609 | if options.tripprefix: 610 | idPrefix = options.tripprefix + "." 611 | trip_generator.source_generator.write_weights( 612 | options.weights_outprefix + SOURCE_SUFFIX, 613 | idPrefix + "src", options.begin, options.end) 614 | trip_generator.sink_generator.write_weights( 615 | options.weights_outprefix + SINK_SUFFIX, 616 | idPrefix + "dst", options.begin, options.end) 617 | if trip_generator.via_generator: 618 | trip_generator.via_generator.write_weights( 619 | options.weights_outprefix + VIA_SUFFIX, 620 | idPrefix + "via", options.begin, options.end) 621 | 622 | # return wether trips could be generated as requested 623 | return trip_generator is not None 624 | 625 | 626 | if __name__ == "__main__": 627 | if not main(get_options()): 628 | sys.exit(1) 629 | -------------------------------------------------------------------------------- /maps/trips.trips.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | --------------------------------------------------------------------------------