-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f37fddb
commit 956143e
Showing
6 changed files
with
948 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
''' | ||
OD populator package main file | ||
Contains functions to generate the od_matrix and parse .taz.xml and .odm files | ||
''' | ||
|
||
import xml.etree.ElementTree as ET | ||
import odmatrix | ||
import odparser | ||
import odloader | ||
|
||
def generate_odmatrix(taz_file, odm_file): | ||
''' | ||
Generates an ODMatrix from the .taz.xml and .odm files | ||
:param taz_file: the path to the .taz.xml file | ||
:type taz_file: str | ||
:param odm_file: the path to the .odm file | ||
:type odm_file: str | ||
return: the OD matrix loaded with the districts and trips from the files | ||
:rtype: odmatrix.ODMatrix | ||
''' | ||
od_matrix = odmatrix.ODMatrix() | ||
|
||
parse_taz_file(od_matrix, taz_file) | ||
parse_odm_file(od_matrix, odm_file) | ||
|
||
return od_matrix | ||
|
||
def parse_taz_file(od_matrix, taz_file): | ||
''' | ||
Fills the od_matrix with the districts found in the taz_file | ||
:param od_matrix: the OD matrix to be filled | ||
:type od_matrix: odmatrix.ODMatrix | ||
:param taz_file: the path to the .taz.xml file | ||
:type taz_file: str | ||
return: the OD matrix loaded with the districts information | ||
:rtype: odmatrix.ODMatrix | ||
''' | ||
taz_tree = ET.parse(taz_file) | ||
|
||
|
||
for element in taz_tree.getroot(): | ||
sources = [] | ||
sinks = [] | ||
for src_snk in element: | ||
|
||
if src_snk.tag == 'tazSource': | ||
|
||
sources.append({ | ||
'id': src_snk.get('id'), | ||
'weight': float(src_snk.get('weight')) | ||
}) | ||
|
||
else: | ||
sinks.append({ | ||
'id': src_snk.get('id'), | ||
'weight': float(src_snk.get('weight')) | ||
}) | ||
|
||
|
||
|
||
taz = odmatrix.TAZ(element.get('id'), sources, sinks) | ||
od_matrix.add_taz(taz) | ||
|
||
return odmatrix | ||
|
||
def parse_odm_file(od_matrix, odm_file): | ||
''' | ||
Fills the od_matrix with trip information of the odm_file. | ||
The matrix must be already filled with the districts information | ||
:param od_matrix: the OD matrix to be filled | ||
:type od_matrix: odmatrix.ODMatrix | ||
:param odm_file: the path to the .odm file | ||
:type odm_file: str | ||
return: the OD matrix loaded with the trip information | ||
:rtype: odmatrix.ODMatrix | ||
''' | ||
odm_parser = odparser.create_parser(odm_file, od_matrix) | ||
odm_parser.parse() | ||
return od_matrix |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
''' | ||
This script can be used standalone or imported in another script. | ||
As a standalone, it connects to a SUMO simulation and when a vehicle leaves | ||
the simulation, it is replaced by a new one. | ||
The origins and destinations of inserted vehicles respect a given OD matrix. | ||
When imported, the user can use the ODKeeper methods act and replace | ||
vehicles in the road network | ||
This script requires the search module available at maslab-googlecode | ||
Created on Jan 12, 2013 | ||
@author: anderson | ||
''' | ||
import traci, sumolib | ||
import os, sys | ||
from optparse import OptionParser | ||
|
||
sys.path.append('..') | ||
import odpopulator | ||
|
||
#looks up on ../lib to import Guilherme's implementation of Dijkstra algorithm | ||
path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'lib')) | ||
if not path in sys.path: sys.path.append(path) | ||
import search | ||
|
||
class ODKeeper(object): | ||
''' | ||
Keeps the load in the road network by replacing vehicles who leave | ||
with new ones, respecting the proportions defined in an OD matrix | ||
''' | ||
|
||
|
||
def __init__(self, road_net, od_matrix, num_veh = 900, max_per_action = 0, aux_prefix = 'aux', | ||
exclude_prefix = None): | ||
''' | ||
Initializes the od-keeper | ||
:param road_net: the road network | ||
:type road_net: sumolib.net.Net | ||
:param od_matrix: the OD matrix loaded with districts and trip information | ||
:type od_matrix: odmatrix.ODMatrix | ||
:param num_veh: the number of vehicles to be kept in the network | ||
:type num_veh: int | ||
:param max_per_action: the max. number of insertions per action of the controller | ||
:type max_per_action: int | ||
:param aux_prefix: the prefix of the vehicles created by the ODLoader | ||
:type aux_prefix: str | ||
:param exclude_prefix: the prefix of the vehicle ID's to be discounted while checking the total | ||
:type exclude_prefix: str | ||
''' | ||
self._road_net = road_net | ||
self._od_matrix = od_matrix | ||
self._num_veh = num_veh | ||
self._max_per_action = max_per_action | ||
self._aux_prefix = aux_prefix | ||
self._exclude_prefix = exclude_prefix | ||
self._insertions = 0 | ||
|
||
def act(self): | ||
''' | ||
Must be called at each timestep. Stores the drivers that departed for | ||
writing them later in an output file | ||
''' | ||
|
||
thisTs = traci.simulation.getCurrentTime() / 1000 | ||
|
||
#does nothing if we have more vehicles than the desired number | ||
if len(traci.vehicle.getIDList()) > self._num_veh: | ||
return | ||
|
||
for vehId in traci.simulation.getArrivedIDList(): | ||
|
||
if self._exclude_prefix is not None and self._exclude_prefix in vehId: | ||
continue | ||
|
||
(orig_taz, dest_taz) = self._od_matrix.select_od_taz() | ||
orig_edg = self._road_net.getEdge(orig_taz.select_source()['id']) | ||
dest_edg = self._road_net.getEdge(dest_taz.select_sink()['id']) | ||
|
||
theRoute = search.dijkstra( | ||
self._road_net, | ||
orig_edg, | ||
dest_edg, None, True | ||
) | ||
#tries again if dest is not reachable from orig | ||
if theRoute is None: | ||
continue | ||
|
||
edges = [edge.getID().encode('utf-8') for edge in theRoute] | ||
|
||
vehId = str(thisTs) + '-' + vehId | ||
traci.route.add(vehId, edges) | ||
traci.vehicle.add(vehId, vehId, traci.vehicle.DEPART_NOW, 5.10, 0) | ||
|
||
#print '%s\t%s\t%d' % (orig.getID(), dest.getID(), traci.simulation.getCurrentTime() / 1000) | ||
|
||
#print ['%.2f' % traci.edge.getLastStepOccupancy(e) for e in edges], traci.simulation.getCurrentTime() / 1000 | ||
|
||
|
||
if __name__ == "__main__": | ||
optParser = OptionParser() | ||
|
||
optParser.add_option("-n", "--net-file", dest="netfile", | ||
help="road network file (mandatory)") | ||
optParser.add_option("-t", "--taz-file", dest="tazfile", | ||
help="traffic assignment zones definition file (mandatory)") | ||
optParser.add_option("-m", "--odm-file", dest="odmfile", | ||
help="OD matrix trips definition file (mandatory)") | ||
optParser.add_option("-l", "--limit-per-ts", type='int', dest="max_per_ts", default=0, | ||
help="Limit the number of vehicles to be inserted at each timestep") | ||
# optParser.add_option("-r", "--route-file", dest="routefile", | ||
# help="route file to be generated") | ||
optParser.add_option("-d", "--driver-number", type="int", dest="numveh", | ||
default=1000, help="desired number of drivers to keep") | ||
optParser.add_option("-b", "--begin", type="int", default=0, help="begin time") | ||
optParser.add_option("-e", "--end", type="int", default=7200, help="end time") | ||
optParser.add_option("-p", "--port", type="int", default=8813, help="TraCI port") | ||
optParser.add_option("-x", "--exclude", type="string", default=None, dest='exclude', | ||
help="Exclude replacing drivers whose ID have the given value") | ||
#optParser.add_option("-s", "--seed", type="int", help="random seed") | ||
|
||
(options, args) = optParser.parse_args() | ||
# if not options.netfile or not options.routefile: | ||
# optParser.print_help() | ||
# sys.exit() | ||
|
||
net = sumolib.net.readNet(options.netfile) | ||
|
||
traci.init(options.port) | ||
|
||
drivers = {} #stores drivers information when they depart | ||
|
||
if options.begin > 0: | ||
print 'Skipping %d timesteps.' % options.begin | ||
traci.simulationStep(options.begin * 1000) | ||
|
||
# for drvid in traci.simulation.getDepartedIDList(): | ||
# drivers[drvid] = { | ||
# 'depart': traci.simulation.getCurrentTime() / 1000, | ||
# 'route': traci.vehicle.getRoute(drvid) | ||
# } | ||
|
||
print 'From ts %d to %d, will replace vehicles' % (options.begin, options.end) | ||
|
||
#creates the odloader and initializes it with the drivers already recorded | ||
od_matrix = odpopulator.generate_odmatrix(options.tazfile, options.odmfile) | ||
loadkeeper = ODKeeper(net, od_matrix, options.numveh, options.max_per_ts, 'aux', options.exclude) | ||
|
||
for i in range(options.begin, options.end): | ||
traci.simulationStep() | ||
loadkeeper.act() | ||
|
||
print 'Now, simulating until all drivers leave the network' | ||
while (True): #simulates the remaining steps till the end | ||
traci.simulationStep() | ||
if len(traci.vehicle.getIDList()) == 0: | ||
break | ||
|
||
traci.close() | ||
|
||
print 'DONE.' | ||
|
||
|
Oops, something went wrong.