Вы находитесь на странице: 1из 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. Therefore, we provide this study
note to supplement the TraCI_tls tutorial. Source codes of this model is hosted here.
First let’s take a look at 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.

Вам также может понравиться