Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 32 additions & 24 deletions docs/web/docs/Tutorials/TraCI4Traffic_Lights.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,44 +42,52 @@ python
python runner.py
```

The route file can also be regenerated independently by running
`python generateRoutes.py` from the tutorial directory.

!!! caution
You need to press start in the simulation gui to run the tutorial.

# Data preparation

The net-definition can be found in the files `cross.nod.xml`,
`cross.edg.xml`, `cross.con.xml` and `cross.det.xml`. The route data is
generated randomly by the script. The vehicles leave the source
according to a Poisson process approximated here by a binomial
distribution. So a parameter `p=1./30` in the script means that a
vehicle is generated every 30 seconds in average.
The network definition is stored in `cross.nod.xml`, `cross.edg.xml`,
`cross.con.xml` and `cross.det.xml`. The signalized intersection uses the
ID `junction`, while the induction loop on the northern approach uses the
ID `north_detector`.

Vehicle demand is generated by `generateRoutes.py` and written to
`data/cross.rou.xml`. The script uses a fixed random seed so that the
example and its tests remain reproducible. Vehicle arrivals are sampled
with a binomial approximation of a Poisson process. For example, a
probability of `p=1./30` corresponds to one vehicle every 30 seconds on
average.

# Code

The control logic resides in the python script *runner.py*. It generates
the routes, acts with the server and controls the traffic light. It
makes use of the TraCI python API bundled with SUMO. A description of
the API can be found at
The example separates scenario generation from online traffic control.
`generateRoutes.py` creates the route file, whereas `runner.py` starts
SUMO, connects through TraCI, reads the induction loop and controls the
traffic light. The route generator is invoked by `runner.py`, so the full
example can still be started with a single command.

The controller uses the TraCI python API bundled with SUMO. A description
of the API can be found at
[TraCI/Interfacing_TraCI_from_Python](../TraCI/Interfacing_TraCI_from_Python.md).
For a detailed list of available functions see the [pydoc generated
documentation](https://sumo.dlr.de/pydoc/traci.html).

# Simulation

The main program is implemented in the script *runner.py*. There, we
first generate the routes as described above. Then `traci.start` is used
to start [sumo-gui](../sumo-gui.md) with the config file
`cross.sumocfg`. The start call also connects our script with the
[sumo-gui](../sumo-gui.md) running as a server.

Then we start to control the simulation. We let the server simulate one
simulation step, read the induction loop and switch the phase of the
traffic light until the end is reached where no vehicle exists on the
road anymore. If we find a vehicle on the induction loop the phase is
switched such that the north-south direction gets green. If no vehicle
is on the detector, and we are not already in the process of switching
(so EW has still green), we try to keep this phase by simply setting it
again. In the end, we close the connection.
When `runner.py` starts, it first calls the route-generation function from
`generateRoutes.py`. It then launches [sumo-gui](../sumo-gui.md) with
`cross.sumocfg` by using `traci.start` and begins the control loop. The
start call also connects the controller to the simulation server.

During each simulation step, the controller checks `north_detector`. If a
vehicle is detected while the east-west direction has green, the program
switches the signal at `junction` toward the north-south phase. Otherwise,
it keeps the current east-west phase. The TraCI connection is closed after
no more vehicles are expected.

# TraCI

Expand Down
1 change: 1 addition & 0 deletions tests/complex/config.complex
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ copy_test_path:ARTEMIS_road_Gear3.csv
copy_test_path:ARTEMIS_urban_Gear3.csv
copy_test_path:cadc_full.csv
copy_test_path:runner.py
copy_test_path:generateRoutes.py
copy_test_path:runnerlib.py
copy_test_path:validate.py
copy_test_path:slope.csv
Expand Down
2 changes: 1 addition & 1 deletion tests/complex/tutorial/traci_tls/data/cross.det.xml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<e1Detector id="0" lane="4i_0" pos="450" freq="30" file="cross.out" friendlyPos="x"/>
<e1Detector id="north_detector" lane="4i_0" pos="450" freq="30" file="cross.out" friendlyPos="x"/>
16 changes: 8 additions & 8 deletions tests/complex/tutorial/traci_tls/data/cross.edg.xml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<edges xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/edges_file.xsd">
<edge id="1i" from="1" to="0" priority="78" numLanes="1" speed="19.444" />
<edge id="1o" from="0" to="1" priority="46" numLanes="1" speed="11.111" />
<edge id="1i" from="1" to="junction" priority="78" numLanes="1" speed="19.444" />
<edge id="1o" from="junction" to="1" priority="46" numLanes="1" speed="11.111" />

<edge id="2i" from="2" to="0" priority="78" numLanes="1" speed="19.444" />
<edge id="2o" from="0" to="2" priority="46" numLanes="1" speed="11.111" />
<edge id="2i" from="2" to="junction" priority="78" numLanes="1" speed="19.444" />
<edge id="2o" from="junction" to="2" priority="46" numLanes="1" speed="11.111" />

<edge id="3i" from="3" to="0" priority="78" numLanes="1" speed="19.444" />
<edge id="3o" from="0" to="3" priority="46" numLanes="1" speed="11.111" />
<edge id="3i" from="3" to="junction" priority="78" numLanes="1" speed="19.444" />
<edge id="3o" from="junction" to="3" priority="46" numLanes="1" speed="11.111" />

<edge id="4i" from="4" to="0" priority="78" numLanes="1" speed="19.444" />
<edge id="4o" from="0" to="4" priority="46" numLanes="1" speed="11.111" />
<edge id="4i" from="4" to="junction" priority="78" numLanes="1" speed="19.444" />
<edge id="4o" from="junction" to="4" priority="46" numLanes="1" speed="11.111" />

<edge id="51i" from="1" to="51" priority="78" numLanes="1" speed="19.444" />
<edge id="51o" from="51" to="1" priority="46" numLanes="1" speed="11.111" />
Expand Down
52 changes: 26 additions & 26 deletions tests/complex/tutorial/traci_tls/data/cross.net.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,17 @@ SPDX-License-Identifier: EPL-2.0

<location netOffset="510.00,510.00" convBoundary="0.00,0.00,1020.00,1020.00" origBoundary="-510.00,-510.00,510.00,510.00" projParameter="!"/>

<edge id=":0_0" function="internal">
<lane id=":0_0_0" index="0" speed="15.28" length="9.50" shape="508.35,514.75 508.35,505.25"/>
<edge id=":junction_0" function="internal">
<lane id=":junction_0_0" index="0" speed="15.28" length="9.50" shape="508.35,514.75 508.35,505.25"/>
</edge>
<edge id=":0_1" function="internal">
<lane id=":0_1_0" index="0" speed="15.28" length="9.50" shape="514.75,511.65 505.25,511.65"/>
<edge id=":junction_1" function="internal">
<lane id=":junction_1_0" index="0" speed="15.28" length="9.50" shape="514.75,511.65 505.25,511.65"/>
</edge>
<edge id=":0_2" function="internal">
<lane id=":0_2_0" index="0" speed="15.28" length="9.50" shape="511.65,505.25 511.65,514.75"/>
<edge id=":junction_2" function="internal">
<lane id=":junction_2_0" index="0" speed="15.28" length="9.50" shape="511.65,505.25 511.65,514.75"/>
</edge>
<edge id=":0_3" function="internal">
<lane id=":0_3_0" index="0" speed="15.28" length="9.50" shape="505.25,508.35 514.75,508.35"/>
<edge id=":junction_3" function="internal">
<lane id=":junction_3_0" index="0" speed="15.28" length="9.50" shape="505.25,508.35 514.75,508.35"/>
</edge>
<edge id=":1_0" function="internal">
<lane id=":1_0_0" index="0" speed="15.28" length="0.10" shape="10.00,511.65 10.00,511.65"/>
Expand Down Expand Up @@ -126,28 +126,28 @@ SPDX-License-Identifier: EPL-2.0
<lane id=":54_0_0" index="0" speed="15.28" length="4.82" shape="511.65,1020.00 510.82,1021.24 510.00,1021.65 509.18,1021.24 508.35,1020.00"/>
</edge>

<edge id="1i" from="1" to="0" priority="78">
<edge id="1i" from="1" to="junction" priority="78">
<lane id="1i_0" index="0" speed="19.44" length="495.25" shape="10.00,508.35 505.25,508.35"/>
</edge>
<edge id="1o" from="0" to="1" priority="46">
<edge id="1o" from="junction" to="1" priority="46">
<lane id="1o_0" index="0" speed="11.11" length="495.25" shape="505.25,511.65 10.00,511.65"/>
</edge>
<edge id="2i" from="2" to="0" priority="78">
<edge id="2i" from="2" to="junction" priority="78">
<lane id="2i_0" index="0" speed="19.44" length="495.25" shape="1010.00,511.65 514.75,511.65"/>
</edge>
<edge id="2o" from="0" to="2" priority="46">
<edge id="2o" from="junction" to="2" priority="46">
<lane id="2o_0" index="0" speed="11.11" length="495.25" shape="514.75,508.35 1010.00,508.35"/>
</edge>
<edge id="3i" from="3" to="0" priority="78">
<edge id="3i" from="3" to="junction" priority="78">
<lane id="3i_0" index="0" speed="19.44" length="495.25" shape="511.65,10.00 511.65,505.25"/>
</edge>
<edge id="3o" from="0" to="3" priority="46">
<edge id="3o" from="junction" to="3" priority="46">
<lane id="3o_0" index="0" speed="11.11" length="495.25" shape="508.35,505.25 508.35,10.00"/>
</edge>
<edge id="4i" from="4" to="0" priority="78">
<edge id="4i" from="4" to="junction" priority="78">
<lane id="4i_0" index="0" speed="19.44" length="495.25" shape="508.35,1010.00 508.35,514.75"/>
</edge>
<edge id="4o" from="0" to="4" priority="46">
<edge id="4o" from="junction" to="4" priority="46">
<lane id="4o_0" index="0" speed="11.11" length="495.25" shape="511.65,514.75 511.65,1010.00"/>
</edge>
<edge id="51i" from="1" to="51" priority="78">
Expand Down Expand Up @@ -175,14 +175,14 @@ SPDX-License-Identifier: EPL-2.0
<lane id="54o_0" index="0" speed="11.11" length="10.00" shape="508.35,1020.00 508.35,1010.00"/>
</edge>

<tlLogic id="0" type="static" programID="0" offset="0">
<tlLogic id="junction" 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>

<junction id="0" type="traffic_light" x="510.00" y="510.00" incLanes="4i_0 2i_0 3i_0 1i_0" intLanes=":0_0_0 :0_1_0 :0_2_0 :0_3_0" shape="506.75,514.75 513.25,514.75 514.75,513.25 514.75,506.75 513.25,505.25 506.75,505.25 505.25,506.75 505.25,513.25">
<junction id="junction" type="traffic_light" x="510.00" y="510.00" incLanes="4i_0 2i_0 3i_0 1i_0" intLanes=":junction_0_0 :junction_1_0 :junction_2_0 :junction_3_0" shape="506.75,514.75 513.25,514.75 514.75,513.25 514.75,506.75 513.25,505.25 506.75,505.25 505.25,506.75 505.25,513.25">
<request index="0" response="0000" foes="1010" cont="0"/>
<request index="1" response="0101" foes="0101" cont="0"/>
<request index="2" response="0000" foes="1010" cont="0"/>
Expand Down Expand Up @@ -234,16 +234,16 @@ SPDX-License-Identifier: EPL-2.0
<junction id=":4_4_0" type="internal" x="510.00" y="1008.35" incLanes=":4_1_0 4o_0" intLanes=":4_2_0"/>
<junction id=":4_5_0" type="internal" x="510.00" y="1011.65" incLanes=":4_3_0 54o_0" intLanes=":4_0_0"/>

<connection from="1i" to="2o" fromLane="0" toLane="0" via=":0_3_0" tl="0" linkIndex="3" dir="s" state="o"/>
<connection from="1i" to="2o" fromLane="0" toLane="0" via=":junction_3_0" tl="junction" linkIndex="3" dir="s" state="o"/>
<connection from="1o" to="51i" fromLane="0" toLane="0" via=":1_0_0" dir="s" state="M"/>
<connection from="1o" to="1i" fromLane="0" toLane="0" via=":1_1_0" dir="t" state="m"/>
<connection from="2i" to="1o" fromLane="0" toLane="0" via=":0_1_0" tl="0" linkIndex="1" dir="s" state="o"/>
<connection from="2i" to="1o" fromLane="0" toLane="0" via=":junction_1_0" tl="junction" linkIndex="1" dir="s" state="o"/>
<connection from="2o" to="52i" fromLane="0" toLane="0" via=":2_2_0" dir="s" state="M"/>
<connection from="2o" to="2i" fromLane="0" toLane="0" via=":2_3_0" dir="t" state="m"/>
<connection from="3i" to="4o" fromLane="0" toLane="0" via=":0_2_0" tl="0" linkIndex="2" dir="s" state="o"/>
<connection from="3i" to="4o" fromLane="0" toLane="0" via=":junction_2_0" tl="junction" linkIndex="2" dir="s" state="o"/>
<connection from="3o" to="53i" fromLane="0" toLane="0" via=":3_0_0" dir="s" state="M"/>
<connection from="3o" to="3i" fromLane="0" toLane="0" via=":3_1_0" dir="t" state="m"/>
<connection from="4i" to="3o" fromLane="0" toLane="0" via=":0_0_0" tl="0" linkIndex="0" dir="s" state="o"/>
<connection from="4i" to="3o" fromLane="0" toLane="0" via=":junction_0_0" tl="junction" linkIndex="0" dir="s" state="o"/>
<connection from="4o" to="54i" fromLane="0" toLane="0" via=":4_2_0" dir="s" state="M"/>
<connection from="4o" to="4i" fromLane="0" toLane="0" via=":4_3_0" dir="t" state="m"/>
<connection from="51i" to="51o" fromLane="0" toLane="0" via=":51_0_0" dir="t" state="M"/>
Expand All @@ -259,10 +259,10 @@ SPDX-License-Identifier: EPL-2.0
<connection from="54o" to="4i" fromLane="0" toLane="0" via=":4_0_0" dir="s" state="M"/>
<connection from="54o" to="54i" fromLane="0" toLane="0" via=":4_1_0" dir="t" state="m"/>

<connection from=":0_0" to="3o" fromLane="0" toLane="0" dir="s" state="M"/>
<connection from=":0_1" to="1o" fromLane="0" toLane="0" dir="s" state="M"/>
<connection from=":0_2" to="4o" fromLane="0" toLane="0" dir="s" state="M"/>
<connection from=":0_3" to="2o" fromLane="0" toLane="0" dir="s" state="M"/>
<connection from=":junction_0" to="3o" fromLane="0" toLane="0" dir="s" state="M"/>
<connection from=":junction_1" to="1o" fromLane="0" toLane="0" dir="s" state="M"/>
<connection from=":junction_2" to="4o" fromLane="0" toLane="0" dir="s" state="M"/>
<connection from=":junction_3" to="2o" fromLane="0" toLane="0" dir="s" state="M"/>
<connection from=":1_0" to="51i" fromLane="0" toLane="0" dir="s" state="M"/>
<connection from=":1_1" to="1i" fromLane="0" toLane="0" via=":1_4_0" dir="s" state="m"/>
<connection from=":1_4" to="1i" fromLane="0" toLane="0" dir="s" state="M"/>
Expand Down
2 changes: 1 addition & 1 deletion tests/complex/tutorial/traci_tls/data/cross.nod.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<nodes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://sumo.dlr.de/xsd/nodes_file.xsd">
<node id="0" x="0.0" y="0.0" type="traffic_light"/>
<node id="junction" x="0.0" y="0.0" type="traffic_light"/>

<node id="1" x="-500.0" y="0.0" type="priority"/>
<node id="2" x="+500.0" y="0.0" type="priority"/>
Expand Down
62 changes: 62 additions & 0 deletions tests/complex/tutorial/traci_tls/generateRoutes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env python
# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
# Copyright (C) 2009-2026 German Aerospace Center (DLR) and others.
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0/
# This Source Code may also be made available under the following Secondary
# Licenses when the conditions for such availability set forth in the Eclipse
# Public License 2.0 are satisfied: GNU General Public License, version 2
# or later which is available at
# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later

# @file generateRoutes.py
# @author Lena Kalleske
# @author Daniel Krajzewicz
# @author Michael Behrisch
# @author Jakob Erdmann
# @date 2009-03-26

from __future__ import absolute_import
from __future__ import print_function

import random


def generate_routefile():
"""Generate deterministic route demand for the TraCI TLS tutorial."""
random.seed(42) # make tests reproducible
N = 3600 # number of time steps
# demand per second from different directions
pWE = 1. / 10
pEW = 1. / 11
pNS = 1. / 30
with open("data/cross.rou.xml", "w") as routes:
print("""<routes>
<vType id="typeWE" accel="0.8" decel="4.5" sigma="0.5" length="5" minGap="2.5" maxSpeed="16.67" \
guiShape="passenger"/>
<vType id="typeNS" accel="0.8" decel="4.5" sigma="0.5" length="7" minGap="3" maxSpeed="25" guiShape="bus"/>

<route id="right" edges="51o 1i 2o 52i" />
<route id="left" edges="52o 2i 1o 51i" />
<route id="down" edges="54o 4i 3o 53i" />""", file=routes)
vehNr = 0
for i in range(N):
if random.uniform(0, 1) < pWE:
print(' <vehicle id="right_%i" type="typeWE" route="right" depart="%i" />' % (
vehNr, i), file=routes)
vehNr += 1
if random.uniform(0, 1) < pEW:
print(' <vehicle id="left_%i" type="typeWE" route="left" depart="%i" />' % (
vehNr, i), file=routes)
vehNr += 1
if random.uniform(0, 1) < pNS:
print(' <vehicle id="down_%i" type="typeNS" route="down" depart="%i" color="1,0,0"/>' % (
vehNr, i), file=routes)
vehNr += 1
print("</routes>", file=routes)


if __name__ == "__main__":
generate_routefile()
49 changes: 10 additions & 39 deletions tests/complex/tutorial/traci_tls/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
import os
import sys
import optparse
import random

from generateRoutes import generate_routefile

# we need to import python modules from the $SUMO_HOME/tools directory
if 'SUMO_HOME' in os.environ:
Expand All @@ -36,41 +37,11 @@
from sumolib import checkBinary # noqa
import traci # noqa


def generate_routefile():
random.seed(42) # make tests reproducible
N = 3600 # number of time steps
# demand per second from different directions
pWE = 1. / 10
pEW = 1. / 11
pNS = 1. / 30
with open("data/cross.rou.xml", "w") as routes:
print("""<routes>
<vType id="typeWE" accel="0.8" decel="4.5" sigma="0.5" length="5" minGap="2.5" maxSpeed="16.67" \
guiShape="passenger"/>
<vType id="typeNS" accel="0.8" decel="4.5" sigma="0.5" length="7" minGap="3" maxSpeed="25" guiShape="bus"/>

<route id="right" edges="51o 1i 2o 52i" />
<route id="left" edges="52o 2i 1o 51i" />
<route id="down" edges="54o 4i 3o 53i" />""", file=routes)
vehNr = 0
for i in range(N):
if random.uniform(0, 1) < pWE:
print(' <vehicle id="right_%i" type="typeWE" route="right" depart="%i" />' % (
vehNr, i), file=routes)
vehNr += 1
if random.uniform(0, 1) < pEW:
print(' <vehicle id="left_%i" type="typeWE" route="left" depart="%i" />' % (
vehNr, i), file=routes)
vehNr += 1
if random.uniform(0, 1) < pNS:
print(' <vehicle id="down_%i" type="typeNS" route="down" depart="%i" color="1,0,0"/>' % (
vehNr, i), file=routes)
vehNr += 1
print("</routes>", file=routes)
TLS_ID = "junction"
DETECTOR_ID = "north_detector"

# The program looks like this
# <tlLogic id="0" type="static" programID="0" offset="0">
# <tlLogic id="junction" type="static" programID="0" offset="0">
# the locations of the tls are NESW
# <phase duration="31" state="GrGr"/>
# <phase duration="6" state="yryr"/>
Expand All @@ -83,17 +54,17 @@ def run():
"""execute the TraCI control loop"""
step = 0
# we start with phase 2 where EW has green
traci.trafficlight.setPhase("0", 2)
traci.trafficlight.setPhase(TLS_ID, 2)
while traci.simulation.getMinExpectedNumber() > 0:
traci.simulationStep()
if traci.trafficlight.getPhase("0") == 2:
if traci.trafficlight.getPhase(TLS_ID) == 2:
# we are not already switching
if traci.inductionloop.getLastStepVehicleNumber("0") > 0:
if traci.inductionloop.getLastStepVehicleNumber(DETECTOR_ID) > 0:
# there is a vehicle from the north, switch
traci.trafficlight.setPhase("0", 3)
traci.trafficlight.setPhase(TLS_ID, 3)
else:
# otherwise try to keep green for EW
traci.trafficlight.setPhase("0", 2)
traci.trafficlight.setPhase(TLS_ID, 2)
step += 1
traci.close()
sys.stdout.flush()
Expand Down