Você está na página 1de 10

A Programmer's Note on SUMO

Mar 10, 2017 / Bo Gao /

We give introduction to the TraCI tool by studying the TraCI_tls model.

Introduction
TraCI_tls is a simple SUMO model developed as part of SUMO’s tutorial on TraCI. It is a perfect
starting point for anyone who is interested in using SUMO and the TraCI tool. After going through the
tutorial material given here, we find that the tutorial may be improved in terms of helping the user to
understand the model from a software’s point of view. The official tutorial also does not provide a
complete list of wiki pages that are essential to help the user to understand the model.
The file structure of TraCI_tls:

+-- data

| +-- cross.nod.xml

| +-- cross.edg.xml

| +-- [cross.typ.xml]

| +-- cross.con.xml

| +-- cross.netccfg

| +-- cross.net.xml

| +-- cross.det.xml

| +-- cross.rou.xml

| +-- cross.sumocfg

| +-- cross.out

+-- embedded

| +--
+-- plain

| +--

+-- embedded.py

+-- runner.py main script

+-- tripinfo.xml

We will begin by going through the files contained in the data folder.

Building the Road Network


Each SUMO model is built on a network of roads, junctions, traffic lights, and other infrastructure
items such as induction loop detectors. Compared to the vehicles and their movements, these are
the static elements of the model. For TraCI, it is good practice to separate these definitions from the
Python scripts in a data folder. Let’s take a look at what’s in this folder.

Nodes and Edges


Nodes and edges are the most basic elements of a SUMO model. Nodes are the reference points on a
map, i.e. the “A” and “B” in “Going from A to B”. Edges are the paths connecting these reference
points.
First, let’s look at cross.nod.xml:
cross.nod.xml
This file defines a list of 9 nodes, each has a unique id, that are
“0”,”1”,”2”,”3”,”4”,”51”,”52”,”53”,”54”. The x and y locations of each node are also given in the
definition of each node. Each node also has a type attribute. Without consulting more documentation, it
is easy to understand what “traffic_light” means being node 0’s type. It must be a junction controlled by
traffic lights. But what does priority mean for all the other nodes? After consulting this
documentation on SUMO’s XML schema, it appeared that this is related to the priority attribute
of edges, so let’s take a look at our next file cross.edg.xml:
cross.edg.xml
From this file we have definition of a bunch of edges, each again has a unique id such as “1i” for the
edge going from node“1” to node “0”. To answer our earlier question regarding the priority typed nodes,
we see that each edge has a priority attribute which has numerical values meaning that edges can be
compared according to their prioritys. In this model, edges going into the juction (node 0), i.e. “*i”
edges, have a higher priority of 78 than those exiting the junction, i.e. “*o” edges which have a lower
priority of 46.
Apart from priority, we also have numLanes and speed as attributes for edges. These are easy to
understand literally. But this file has lots of repetitive codes, and this is not ideal from a programming
point of view. Not to worry though, SUMO has this covered with a *.typ.xml file which we will take a
look at in the next section.
Before we finish this section, let’s quickly summarise what we know about the definitions of nodes and
edges so far of TraCI_tls with this illustration:

Further reading: On node types (extract from here:):


all possible node types
Define edge types with a *.typ.xml file
Indeed, there is no cross.typ.xml file included in this model, but there could have been one and it would
have looked like this:
cross.typ.xml
With the addition of this cross.typ.xml file, the cross.edg.xml file can be simplified as:
modified cross.edg.xml
Compare this to the original version:
original cross.edg.xml
You can see that edge attributes such as priority and numLanes have been extracted and grouped together
in the cross.typ.xml file. This is useful when you have many edges of the same type, and it is also a good
practice from a programming point of view.
Further reading: To get a full list of the attributes an edge may have, consult SUMO’s documentation
on its *.typ.xml file here.

Connect edges with a *.con.xml file


We now have 8 edges all associated with node 0, a traffic_light typed node. These edges have yet to be
connected together, i.e. rules are yet to be defined to route vehicles from one edge to another. Let’s see
how this is done in TraCI_tls:
cross.con.xml
The code for connections are self-explanatory with from and to to establish a link between two edges
which we illustrate below:

Indeed, from and to are the most essential attributes of a connection. Other attributes are also available
for defining a connection:
connection attributes
According to these attributes, there are a lot you can do with a connection, but let’s concentrate on
TraCI_tls for now.
Further reading on connections is available here .

Generate *.net.xml, with netconvert and *.netccfg


Before we dive deeper in the data folder, let’s take a look at what assets we have got so far for the
TraCI_tls model:
.+-- data

| +-- cross.nod.xml nodes, junctions

| +-- cross.edg.xml edges, paths, roads

| +-- [cross.typ.xml] edge types

| +-- cross.con.xml connection between edges

| +-- cross.netccfg

| +-- cross.net.xml

| +-- cross.rou.xml

| +-- cross.sumocfg

| +-- cross.det.xml

| +-- cross.out

With the 4 checked files, we are now ready to put the nodes, edges, and connections together to construct
a complete “network”. In order to do this, first we need to write a network configuration file
named cross.netccfg:
cross.netccfg
Tip: Note that both cross.netccfg and cross.netc.cfg are acceptable suffixes to SUMO’s GUI. If you are
not using the GUI then this file can have any name as long as you give it correctly to netconvert.
cross.netccfg is very literal with input and output files specified in the first two sections.
The verbose option in the report section controls the verbose output behaviour of netconvert.
On a command line, execute the following command to generate a cross.net.xml file.

netconvert -c cross.netccfg

netconvert is a SUMO binary just like sumo and sumo-gui. If you compiled SUMO from source then this
together with all other SUMO binaries should be in your bin folder, for example in my case this is
the ~/sumo-0.29.0/bin/ folder. If you make install-ed, then these binaries will be located somewhere
like /usr/local/bin/. Issue a which netconvert command to find out where it is.
Tip: The purpose of the cross.netccfg file is to make calling netconvert earlier for the user.
Without cross.netccfg, an equivalent result can be achieved by executing
netconvert -n cross.nod.xml -e cross.edg.xml -x cross.con.xml -o cross.net.xml

on command line.
Note: Although it is generated by netconvert automatically, it is worth taking a look at cross.net.xml as it
gives detail on the default behaviours of the netconvert tool. We will see more on this file later on.
Further reading on netconvert is available here.

Place Detectors with *.det.xml


cross.det.xml
Further reading on detectors is available here, detectors TraCI

Network Summary
Let’s summarise the process of generating a network with the following illustration:
Our progress through the data folder looks like this:

+-- data

| +-- cross.nod.xml nodes, junctions

| +-- cross.edg.xml edges, paths, roads

| +-- [cross.typ.xml] edge types

| +-- cross.con.xml connection between edges

| +-- cross.netccfg network configuration

| +-- cross.net.xml network

| +-- cross.det.xml detectors

| +-- cross.rou.xml

| +-- cross.sumocfg

| +-- cross.out

Note that cross.det.xml is not part of the network for a SUMO model. We will see it in action later on.
Defining Traffic
Having constructed the road network in the previous section, the stage is now ready for our actors.

Add Vehicles and Routes with *.rou.xml


To get traffic moving on our network, we first need to define vehicles and routes for vehicles to travel
along. This is done in the cross.rou.xml file:
cross.rou.xml
In SUMO, a route is a sequence of connected edges. In this file, we see that a route is defined with
the route label, and its edges attribute contains a space-delimited string of edge names giving the
sequence of edges a vehicle is to travel on along this route. In this model, as their id suggest, we have
two routes traveling horizontally in each direction, and one from north (top) to south (bottom). All
three routes travel through the junction at node “0”.
As well as routes, vehicles and their type vTypes are also defined in cross.rou.xml. In TraCI_tls, we have
two types of vehicles: typeWE for horizontally traveling vehicles and typeNS for vertical traveling
vehicles.
We can see that the length of this file is dependent on the number of vehicles included in the simulation
and that implies that this file could be significantly longer than the other files in the data folder.
Therefore, it is preferable to generate this file with a script. This takes us to the runner.py file in the root
folder of this model.
Further reading on the definition of vehicles, vehicle types, and routes is available here

Main Script runner.py


We see from cross.rou.xml that defining vehicles by hand is a labouring task, so we now
introduce runner.py which generates traffic information according to given distributions. runner.py is a
script with code logic rather than the XML-based data files we have seen so far from this model. Let’s
look at this script by sections.
Generate Traffic
First, to continue our observation from the cross.rou.xml file, let’s take a look at
the generate_routefile function:
generate_routefile()
From this we can see that indeed the cross.rou.xml file in the data folder is produced by this function. The
definitions of the 2 vTypes and 3 routes are written as is. Then, at each time step ( i/N), a vehicle is
generated for each of the 3 routes according to its respective probability ( pWE, pEW, pNS).
The route attributes given to these 3 vehicles ensure they are assigned to the correct route, and
the depart attribute specifies the time step at which they join the network. Additionally, the vehicles
traveling from north to south is given the red colour ( color="1,0,0") to distinguish themselves.
Control Traffic with Traffic Lights and Induction Loop
Next, let’s take a look at the run() function
run()
5 methods of traci are called in this control loop:
Method Description

trafficlights.setPhase(string,int) -> None Set the given traffic light to the given phase.
Read more after this table.

simulation.getMinExpectedNumber() -> int Returns the number of vehicles which are in


the net plus the ones still waiting to start.
This number may be smaller than the actual
number of vehicles still to come because of
delayed route file parsing. If the number is 0
however, it is guaranteed that all route files
have been parsed completely and all
vehicles have left the network.

simulationStep(int=0) Forces SUMO to perform simulation. If


given input is 0, SUMO performs exactly
one time step. Otherwise SUMO performs
the simulation until the given time step is
reached. If the given time step is smaller
than or equal to the current simulation step
then SUMO does nothing. Read more here.

inductionloop.getLastStepVehicleNumber(string) Returns the number of vehicles that were on


-> int the named induction loop within the last
simulation step.

traci.close() Performed at the end of the simulation. Stop


the simulation and SUMO.

Let’s focus on the trafficlights.setPhase method. For a start, what does traci.trafficlights.getPhase("0") ==
2 do? We know that it sets the traffic light at node 0 to phase 2, but what exactly is phase 2? And how is it
giving green to EW traffic? Going through the model files we went through for this model, our only
definition relevant to this traffic light is <node id="0" x="0.0" y="0.0" type="traffic_light"/> in cross.nod.xml.
Therefore the phase data of this junction must have a default behaviour, but what is the default
behaviour of this type of function? The answer to this question lies in the cross.net.xml file which
includes the following definition ( tlLogic) for this traffic light:

<tlLogic id="0" type="static" programID="0" offset="0">


<phase duration="31" state="GrGr"/>

<phase duration="6" state="yryr"/>

<phase duration="31" state="rGrG"/>

<phase duration="6" state="ryry"/>

</tlLogic>

This teels us that phase 2 is <phase duration="31" state="rGrG"/>. From this, we understand that each
character in the state attribute corresponds to a positive number of connections (as put in the official
documentation: “a one-to-n dependency between signals and links is implemented, this means each
signal may control more than a single link - though networks generated by NETCONVERT or
NETGENERATE usually use one signal per link”, with “link” meaning “connection”). We know that
we have 4 connections defined in cross.con.xml and they corresponds to the 4 characters in
the state attribute of each phase.
The next question is which character corresponds to which connection? Again we need to
consult cross.net.xml:

<connection from="1i" to="2o" fromLane="0" toLane="0" via=":0_3_0" tl="0" linkIndex="3" dir="s" state="o"/>

<connection from="2i" to="1o" fromLane="0" toLane="0" via=":0_1_0" tl="0" linkIndex="1" dir="s" state="o"/>

...<connection from="3i" to="4o" fromLane="0" toLane="0" via=":0_2_0" tl="0" linkIndex="2" dir="s" state="o"/>

...<connection from="4i" to="3o" fromLane="0" toLane="0" via=":0_0_0" tl="0" linkIndex="0" dir="s" state="o"/>

The linkIndex attributes of these 4 connections give us their order in the state string, meaning for
example phase 0 is:
1. the connection from “4i” to “3o” is “r”
2. the connection from “3i” to “4o” is “G”
3. the connection from “2i” to “1o” is “r”
4. the connection from “1i” to “2o” is “G”
We illustrate the use of linkIndex as below:
getLastStepVehicleNumber(self, loopID)

getLastStepVehicleNumber(string) -> integer

Returns the number of vehicles that were on the named induction loop within the last simulation step.

Boilerplates of runner.py
Thirdly, let’s look at the header section of runner.py:
header of runner.py
The try block tries to locate and include the TraCI python module traci and sumolib from
the $SUMO_HOME/tools directory.
Finally, once import has been completed, the script triggers the sumo model and then execute
the run() function to establish the connection with the following code section:
entry point of runner.py
Here, we that after the binary has been located, routes and vehicles are generated by generate_routefile(),
then a sumo server is started and a connection is established between the model and TraCI, before
finally the controls are executed with the run() function. We also see the use of cross.sumocfg when the
sumo binary is called.
cross.sumocfg
cross.sumocfg is similar to cross.netccfg in functionalities. It provides the parameters for the sumo/sumo-
gui binary rather than to the netconvert tool which is aided by cross.netccfg.

Further Reading: additional files

Start the simulation in sumo-gui


By executing python runner.py, by default the GUI version of sumo is triggered:
Adjust the “Delays” parameter and start the simulation by clicking on the button.

Você também pode gostar