2025 Tutorial

This tutorial shows railway simulation, GTFS, detector count import, electric vehicles, automated charging and more!

Files#

Video#

Watch the 2025 Tutorial

Transcription#

Intro#

Welcome to this year's SUMO tutorial. I enjoy doing this every year and I hope I brought you some interesting things. I already overheard that some people in the audience are interested in railway simulation and I'm pretty sure you will find something for your taste. You are not of course expected to follow this tutorial along on your computer. I'm afraid I will be a bit too fast but everything will be recorded every click, every keystroke. So if you really want to follow up on these things then you are perfectly able to do so later. So the topics for today. Of course we will start with building a scenario from a few clicks based on the OSM Web Wizard tool. And then we will go into the topic of railway simulation. We are going to build a small simulation model of the light rail transport of the city of Berlin. And we will let the trains run on time according to, well, more or less according to the schedule that are officially in place right now, and as you may have heard, we have a major disruption in Berlin - a big bridge has broken down and caused all kinds of trouble. And it will not only be rails - Trains riding around - we will have passengers riding those rails and switching trains. This will be the first part of the tutorial. And in the second part we again start with a bit of a Web Wizard. We will build another scenario this time for road transport. And again we will populate it with real world data, instead of the typical thing where we start with random traffic because there aren't any good sources. This time we will look at data that is published by the city of Berlin: localized counts and I will show you how to import all those detectors and all the counting data that comes with it. And in the final part we will switch the whole scenario to electric driving, see how that goes, see where the batteries run low and then also learn how we can fix this with automated charging in the simulation. So, enjoy.

osmWebWizard#

The OSM Web Wizard tool has been with SUMO for quite some years. You can find it in the tools directory of SUMO. Well, anyway, if you look at the tools directory of your SUMO installation, wherever that is, there's a big tools folder and you can find it here. It's called osmWebWizard. Of course, if you've used the installer, you will just have it in your start menu. And when you launch it, it will give you a screen about like this, where you can pick a piece of the map for you to build your scenario off. In this instance, we're using the inner ring of the Berlin light rail system. And there is one section up here where you can, actually it's here, where you can select the road types that you want to import. And well, actually, let's show this live so you know what I'm talking about. Okay, so obviously the the internet is not working flawlessly, but it doesn't matter. This is the screen I want to show you. This is the section where you can select the road types that you want to import. Be aware that OpenStreetMap has some limitations on the amount of data you can download over the API at once. So if you want a larger scenario, it really helps to deselect the things that you're not interested. So in this case, we would deselect everything and just keep the light rail, which is here, and so on. And then when we do this, looking back at the slides, we can deselect some other things. We don't need any random traffic, but we do want to have this "Import Public Transport" checkbox. We also don't need any background polygons, satellite background, none of that. Only the basic rail network with some public transport on it. And when we run this, we'll get a scenario that looks about like this.

Railway simulation#

So we have trains, running around the network, and doing their thing. This is really fast right now. I only want to note that we do have some interesting effects here. We have some teleports. And if we look at the warning messages, it says, waiting too long, teleported, and then probably skipped some stops. So what's going on here? Let's look at what this scenario does. It's a railway scenario. And as you know, there are some very special rules that guide the safety of a railway system. The most common case over the world is block signaling. So the network, the rail network, is divided into blocks, separated by railway signals, and there may only be one train in the block at any one time. And this pretty much avoids the collisions, if everything goes right. And there are lots of features that make sure trains cannot run over a red signal. And so basically the railway transportation is very, very safe. Now, the railway network that we build right here, from public available data from OpenStreetMap, it does contain some rail signals. I'll highlight these by enlarging them a bit. And so you can see all these little green and red lines. And if you look very closely, you may notice that the density of these colored lines is not even throughout the network. If you look down here, there are larger gaps compared to over there. And, well, why would that be? It's public data, it's managed by volunteers, who put in the known locations of the tracks, and they put in the signals, and these people are not perfect. It's not official data from the German rail authorities. So this means some of these signaling blocks are longer than they are in reality. This is a modeling problem. And if you have long blocks, it means the railway system is not as efficient, because trains have to have a much larger separation in space. They take up more space. They take up a larger block. And this impacts punctuality, of course, in a negative way. And then you have trains that wait a bit too long. And by the default rule of SUMO, after five minutes, they get teleported away, which is not ideal for a rail simulation, but it's just the default setting. So what are we going to do? We're going to set an option, when we build the network, it's called --railway.signal.guess.by-stops, and it just means that at every public transport stop, we put in at least one railway signal at the entry and at the exit. So it's a heuristic to work around limitations in our OpenStreetMap data. There's another warning that I won't want to go into detail too much, warnings of the type block exceeds maximum length. These are not actually the signaling blocks, they are larger sections that are needed to check for deadlock in the railway system and to prevent them and the Berlin light rail system it is a big circle and it's a bit harder to check for these deadlocks in a circular structure. But for now this does not concern us, we will just rebuild the network with this option and then we'll have a better network.

So I prepared another configuration file and then of course when we do this we have to rebuild the traffic because we split the network whenever there's a rail signal and then all the sequences of edges where the trains are riding they are not quite correct anymore. But a web wizard scenario comes with all the tooling that is needed to rebuild all the components. So after rebuilding the network we just rebuild the public transport traffic and now we can run this again and this time there won't be any warnings, the trains will run. And let's look at this in a bit more detail, let's have this run more slowly. So we reload the simulation, Ctrl + R as you see. First of all we are coloring the trains and we're coloring by a metric that is relevant for public transport, it's by the delay. So every train has a stop that it's approaching usually, unless it's going out of service at the end of the day, and the stop has some scheduled timings associated with it, a scheduled arrival, scheduled departure. And here we're just coloring the trains according to the delay that they have with respect to the schedule. So blue is good, blue means no delay and as the network fills we do have some delayed trains. And actually if we look a bit closer, we can find instances of a bunching phenomenon which is known from reality where a couple of vehicles are following each other closely on the track. Actually, we'll see this in the next case because this is not enough traffic. What have we seen here? We saw very rough data from OpenStreetMap. It's just the info of where the lines run and if we're lucky also the the period between trains, but there's actually not a detailed time schedule associated with it. So let's go on to the next step. Let's go on to getting real world data.

Berlin S-Bahn simulation - Schedule#

And there is such a source. The data format is called GTFS, General Transit Feed Specification, originally introduced by Google, back then it was called Google Transit Feed Specification, but pretty much now every public transport system tries to provide data in this format. And we have the tooling to import this GTFS data. In this case it's provided by the Berlin authorities, Verkehrsverbund Berlin-Brandenburg (VBB). The file for the whole city is pretty large (I don't want to include it in the tutorial) So I actually trimmed it down to just include light rail transport. If you want to see how this such trimming of GTFS data can be done, I even put the tool, the trimming tool, into the tutorial. So you can just look at the script and see how it works. And then we have a much smaller file with the GTFS data. And we have a tool that imports this. It's called, well, gtfs2pt.py pt standing for Public Transport. This is the file, the GTFS file. It's always a zip. And we have to pick a date. Because, well, we want to, we don't want to simulate the whole year. We just want to simulate a smaller data set. We give the network and we give the stops. Now this is interesting. If you have such GTFS data it has to be mapped onto your network somehow and usually you just have some very rough coordinates latitude longitude for where a station is. But the station consists of many things. It consists of different platforms. Sometimes these platforms are on different levels. So it's definitely more than one coordinate but all that GTFS gives you is one coordinate. And so there is some mapping effort involved and actually multiple solutions how this can be done. But one solution is to provide known public transport stops which we can read from OpenStreetMap. So the thing we just imported from OSM is still useful. We pass these stops on to the importer and then it has a much easier time of finding where these trains actually are supposed to stop. So another thing that's very important in a railway simulation is to know which directions the tracks are used in. Of course a track can be used in both directions but it's not typically being used that way. When we're not talking about disruptions then we have a preferred direction for every track. This is not normally known in our database. It can be given in OSM but usually it's missing. So it really helps to know on which tracks these trains are stopping from the OSM data. It implies the preferred movement direction. So when we do this we get a simulation.

So we're actually now in the next folder where we have an import script that you can use to import the public transport network. So let's do this. So we have a simulation here. It basically runs this script gtfs2pt and it takes a few seconds. And then we will have our simulation. Any time now. So by this you see it's live. It's not scripted. Maybe I should have scripted it to save a few seconds. But now it's done. And we have our scenario. So let's look at this again. Now we have a lot more traffic and we have a lot more problems. Plenty of problems. So I told you the color is the delay and all these trains are cherry red. So something is really wrong here. Now what is that? It's a teaching opportunity of course. So the data from the public transport authorities includes all the known disruptions in the network like a bridge that cannot be used. And in this case the train service differs from normal operations. Trains do run on the wrong side of the track, of the double track lines, so they go places where they usually don't go. And in the OpenStreetMap data we usually don't have short-term disruptions. So there's a mismatch between these two data sources that we're using when we decide what coordinate corresponds to which track when the train has to stop at a specific station. So what can we do? The easiest thing we can do is switch the network into a mode where we say every, really every track is supposed to be usable in both directions. Sometimes it helps not to do this because constraining the solution set, helps it to avoid bad solutions. But in this case, we know there's a disruption, so we have to rebuild the network and say we don't know where the trains go, like, make sure every track can be used in both directions. So this is one option that we can give to netconvert to build the network again. And another thing we did is, well, you could say is cheating, we, when we load these stops, that say these are potential locations where trains can stop, we actually add a new file with two extra stops that weren't in the OpenStreetMap data where we say, well, if you go to this location, actually this is the track you can stop on. So it's pretty fine-grained, but it's also a special case because we are dealing with the disruption. So when we do this, we go back and run the netconvert again, with additional options, and then actually we have to build again. This was the thing that took a few seconds. So, while we're at this, while we're waiting for the importer to go, let's look at some of the details on the railway system. We see, what can you do with the simulation? You can see, of course, the trains where they stand at their signals, but you can also interact with these signals. Right-click on the colored bars and you have some information. You see, actually, here the IDs of the trains that are blocking passage. So this train has to wait because some other train is in the wrong spot or in an obstructing spot. And there's a concept in SUMO called driveways (the German term is Fahrweg), which is actually a section of track that is a relevant unit for railway operation. And there are outputs of the simulation that tell you, what are these driveways and how are they in conflict with each other. And all these structures, they are automatically generated at runtime. So the network is analyzed and all the things that usually railway engineers would do, and they would pour and waste lots of paper and all that - make good use of a lot of paper - and figure out how to separate the network in these sections and how to avoid that trains run into each other. All this happens inside sumo at runtime to figure out how these rail signals are dependent on each other and on the location of the trains in the system. So going back, this has concluded. And now we can run our railway simulation again. And this time it should run smoothly. So as you can see, no big bunching. We have some pieces where trains follow each other closely, so just because one train is stopped in the station, it forces other trains to wait behind. And for buses, it's called bus bunching. I guess this is then train bunching. So this is our Berlin light rail system. Some parts of it, it's cut off there. It's actually a bit bigger. And now we want to put passengers in it. So how would we do this? Oh yeah, a small aside here. There are some instances in the railway system, especially at the end of a line, where trains sometimes use a different track because after that they switch directions. And so from the data of OpenStreetMap, it's not always totally clear what the preferred driving direction is on any one track. Because there are some stops that are only used sometimes, but they're all there as candidates. So there may still be issues in this simulation where sometimes trains do run on the wrong side of a double-track line. And of course, this has an impact on the efficiency of train operations. So this is something where one still has to look and see whether everything is working all right. But SUMO does provide tooling to point out places where implausible behavior takes place. For example, if a train switches direction, which sometimes is necessary, at the end of the line you have to reverse, but you can find all the locations in the network where this takes place, direction switching. And if they're not the terminals, then you know probably there's some problem with your network model.

Berlin S-Bahn simulation - Passengers#

All right, now to the passengers. Well, they have to, they should go from one public transport stop to some other stop. And we don't have any data on this, so we randomized the passenger demand. But sometimes when you go from one end of the city to the other, you can't take a direct train. You have to switch trains. This means also you have to sometimes switch platforms. And so our Pure Rail network needs to be extended with a few, let's say, pedestrian edges, pedestrian roads, that help passengers switch from one platform to another. We have a small tool for this, it's called generateStationEdges.py, basically, it puts on every public train station, it places a single edge and then connects all the platforms with that edge, like the tunnel that goes below the tracks, the pedestrian tunnel, something like that. So we have this tool, and in this little build script, we patch the network with these extra edges. Actually, I'll show you the tool because it's not too intimidating. We are by now in the next folder. And this is what the tool looks like. It generates some new edges. I'm not sure if you can read this. This is the Python tool. Then it calls netconvert again to incorporate these additional edges into the network. Then we randomize the passenger demand. And that's already it. In the end, this is not part of the simulation, this is just an analysis. We can see what sequences of train rides and switches Persons actually did. So let's run this. This is just for information. So here is the static analysis of the generated passenger itineraries. They do things like stop, ride public transport, and then walk. Or they do walk, ride public transport, walk, ride again, ride again, this time from the same platform, and then walk some more. So all these possible kinds of trips with some little statistics to see how often they occur. And maybe you want to know how to get these random passenger trips. So let's look at the configuration file for random trips. We constrain the time. So we let them ride between 7 and 8 o'clock. We have to define the network. And of course, the public transport stops at which they can start. And in order to do the intermodal routing, the public transport routing, where to switch trains, we also need to define the train schedules, which are still taken from the previous step of the tutorial from the GTFS part. So you can see these paths here. And then we will generate the ready routes. These are person trips. The trips thing is there to actually activate the intermodal routing. Trips means someone has to figure out how to get from A to B. And we start our trips at the stations and we also end them at the stations. And then all the trips are allowed to use public transport. They could also be used to use their car or only walk. But in our light rail simulation, obviously they all have to use public transport. And then there's this innocent little option, validate value="true", which makes sure that we throw away trips that are not feasible.

So if there were any parts of the network not being connected to each other, then we would already filter these out. And actually, a small spoiler, now this option does even more. It figures out how to replace all these invalid trips with the correct number of missing trips. So you always get a predictable amount of trips out of random trips now, which was a long requested feature over the years. So let's look at that simulation. So as mentioned before, they start at 7 o'clock. We started the trains a bit earlier to have them already running in the network. And here you can see all these colored circles, each circle being a pedestrian, a person, not a pedestrian. And here is the meaning of the colors. Blue means they're riding a train. Yellow means they're waiting for a ride. This here, this light blue means they are assessing a bus stop. So they're somehow transferring between platforms at a station. And then, well, you have them being whisked around in the railway system. And each of them reaching their destination. Let's have this again and see the trains along with them. So we'll make the trains a lot bigger as well. But of course, we can also zoom in and see them riding the trains. And maybe track a train. This was a shift click I did on the train to track it. And at some point, we can see other passengers get in and the first ones get out. Of course, the signals have to be obeyed first. And now they left. And I think this might be Ostkreuz station, where they then have to go up a level. To switch to another rail line. So this is the railway simulation, mostly based on public data with only a small bit of randomness thrown in to have the passenger demand. And this concludes the first part of our tutorial. Well, now there are some closing remarks on the limitations of this. So if you were trying to build not a scenario of the Berlin network only for the inner ring, but of the whole city of Berlin, you would notice that on the outskirts of the city, some light rail lines actually run on tracks for the big rail system. So they are shared tracks. And so if you build your network with light rail only, you have some gaps in your network. That's not good. And also, if you get everything that's tagged as light rail, then you get far too much. You get all the service yards and some industrial branch lines. So you have lots of tracks that will never be used in your public transport simulation. They may look nice, all these service yards with the turntables, but they're not particularly useful most of the time. So what you can actually do is, you can import from OpenStreetMap some usage classification of the tracks, things like a main line or service yard, stuff like that. And you do this by loading another kind of typemap when you import your data. It's called osmNetconvertRailUsage.typ.xml and then all the tracks in the network will have this additional marker that says what they are used for. And then you can do a lot smarter filtering. Then basically you filter everything where the light rail may drive. And it may drive there even on the main line if some public transport route goes there. So if you're interested in this, we have this as a public scenario. It's online under this address, it's the sumo-berlin scenario. And it has this particular option for building the S-Bahn, the light rail scenario for the whole city. So if you interested in this, this is what you can look at to get more details. Now this really concludes the first part of the tutorial. Any questions, note them down. We will have the ask us anything session later.

Berlin, counting data import#

Now on to everybody who isn't particularly interested in trains and wants to see some roads and cars on the roads. Again, we start with the Web Wizard. This time we set this other checkbox that's called "Car-only network", and so we only use the main road types this time to import it. And we get a fairly large section of Berlin. It's this area we're in called Berlin Treptow-Köpenick. And we are round about here, if you care to know. And well, we're not going to activate any random traffic. I've crossed this out. Because this time we want to do things differently. We want to use real world counting data. And where do we get this? Well, this is not as nice as the GTFS case where all the world agreed on a single data format. It's more or less every city on their own. But, well, if you would call it the standard, oftentimes you get stuff at comma separated values, CSV files. And so in this case, a public data portal from the city of Berlin gave us the following two files. It gave us an Excel file of all the detector locations in the city. And it gives us lots of CSV files with hourly counting data for these detectors. This is good enough. So we save the Excel file as comma separated values. This is how it looks. This is just a screenshot, obviously. And this is how the data, the hourly counting data looks. So you have the name of the counting location. This could either be a lane location or it could be a cross section. So all the lanes of one direction of road. And then we have the date, of course. The hour, this would be this. Just a running number between 0 and 23. And we have counting values for different types of vehicles. So mainly the individual transport. And then this is PKV. And then we have, what is it? Right, trucks. There it is, LKV, the trucks. And so, what do we do with this?

This time, for this tutorial, I'm not going to be showing you a lot of clicking in netedit. This time it's all, or mostly, tools and how to use them. So we have two sets of tools. The first one to get the traffic counting data into a usable format. And then a second set of tools to actually build traffic on that. Because it's not totally trivial to go from counting data to traffic. Some of you may know. So first of all, we import the detector locations, which would have been the Excel file, which we converted to CSV. And we have this mapdDetectors.py tool, which basically looks at the longitud, latitude data and places this on a road. Looking up the appropriate column names. So, Länge and Breite are the German words for longitude, latitude. And, well, because it's Germany, they have to write Länge with an umlaut, with an "ä" and if you paste such letters into a terminal, you run into encoding problems, because the Windows terminal has some ideas on how an "ä" should look. Whereas people writing this in files may have another idea. So I cheated. I renamed it in the CSV file. I just removed the umlaut to not have to deal with this today. So we are detecting this. And out comes a file with a perfectly serviceable sumo detectors, so it's called det.add.xml here, this is the output name we assigned. And if we look at this, it's really just a sumo file with induction loops. Note that there are lots of extra lines in there. This is because we set this option --write-params. So every column in this data file that tells us something about when this detector was last serviced or whatever it does, we just put this into this file so we can see it in the sumo-gui. And the second tool we run is called edgeDataFromFlow.py. This is the CSV file with the hourly counts, and we have to set all kinds of options just to tell it what the columns are named and what timing is actually in that. So it could be data for five minute intervals. But in this case, we know it's hourly, so at some point we have to say one data point corresponds to 3600 seconds. So this is the time scale here. And then we get a new file called countdata.xml. So we look into this file very briefly. And it looks like this. We have intervals. They all have a beginning and end time. So you can see quickly this is hourly data. And then we have an edge ID. And then we actually have all these data columns that we already saw for the counts of the trucks and the cars. All right.

So next step is this group of tools where we turn this counting data into cars that ride through the network. SUMO brings several tools that try to tackle this problem. Some have their advantages and disadvantages. And most feature complete tool that I'm advocating to use to all of you is called routeSampler.py, the reason why this is a useful tool is because it gives you more control about how to solve this problem. Basically, the problem is under constraint. There are so many different ways cars can drive and still have the same counting data registered at the detectors. So you need some way to constrain the solution space. And one possible constraint is to say, well, I know our typical routes through my network, because the typical routes are not big detours that drive in circles, but the typical routes are shorter paths or faster paths between locations in the network. So what we can do is we can build random trips all over our network. Random trips that are not detours but rather reasonable paths through the network. So this is what we do here. We call randomTrips.py and we just generate a bunch of candidate routes throughout our network and then the Route Sampler tool. So these are the random routes here in pink. And the Route Sampler tool uses these candidate routes as inputs and then tries to find a subset of them and a multiplicity of those that match the recorded counts. And this is still an under constraint problem, but at least the solution won't have any awful detours in it. So this is a good one. And then we can give some more options. We say the cars, when they're running the network, they should probably drive already with a good speed because they're not departing, but rather they're coming into the scenario on the edges. So they're already driving at speed when they enter the scenario. This would be this option here, for example. And we want to put them on reasonable lanes. So we don't want to put a car that is about to turn left on the rightmost lane in front of a big intersection because that would create a mess if the car has to do many lane changes over a short distance.

So we make sure that all the cars depart or insert, start the scenario on lanes that are reasonable, a reasonable fit for where they want to go. All of these things, all of those four tools, are called in a script called build.bat, a batch file, and then you have a scenario. So let's look at the scenario with counting data. So you see it's a fairly big section. This might be, I don't know, eight kilometers times five kilometers maybe. And when we run this in the standard settings, we won't see much. So what I like to do when I don't have anything, have something preconfigured, but I'll show you what I do. I check this button here for the vehicle options. Which is called "draw the cars with constant size", so I see them much bigger when I'm zoomed out. And then maybe to have some more info, let's color them according to their speed. And now we can see them driving around the network. Well, we know that what we see here, all the cars, they actually match the counting data. How do we know this? When we run the tool, the import script, it tells us this. If you run route sampler, it will give you some information on the quality of the fit between the loaded counting data and the achieved counting data from the routes. So it's not a time-based fit. It's just, I saw so many cars at this location, and the routes that I generated, they have the same number of cars passing that same location in a certain time interval, or at least departing in a certain time interval. And then, so it tells you, basically, we got 100%. Well, this might surprise you that we get 100% fit in every interval. But again, this is because the problem is so under-constrained. It is very easy to find a solution here. If we had more detectors, it would be harder. Also, if we had more detailed timing data, it would be much harder. This is a topic for another time. So in this case, we did find a solution. Just looking at this, eyeballing this, I see that there's probably a problem here because this is one of the main roads in this scenario, and it just doesn't have enough cars on it. Somehow, all the counts are matched even by cars that don't go there. So, yeah. Be aware that if you do this, even if you do everything right, it may be that your data just doesn't constrain the problem enough. In this case, it would be easy to put in some additional information that says, I expect a certain number of cars here on that road, and that would fix the problem. But you need to go that extra mile, if you know enough about your scenario, and you want to make sure that it matches all your assumptions.

Electric Vehicles#

So, we do have a scenario, it does match counting data. Where to go from here? Well, we go into the future, obviously, where everybody is driving electric vehicles. This is hard in reality to get everybody to switch, but it's very easy in SUMO, and I'll show you how to do it. So basically, you just have to reconfigure the default vehicle type, and you just say, every car now has a battery in it. This is the line that does this: has.battery.device value is true. Now, this is the easy part. Everybody's driving electric. The world would be perfect. But this is too easy. We want to make the world a little harder. So, in our little world, we make sure that not everybody starts with a full battery. So, we set this other thing here, this other parameter, that configures the initial charge of the battery (device.battery.chargeLevel). And notice that I'm giving a single configuration line here to define a distribution of values. So, this is a new thing in SUMO that some of the input parameters you can give, you can not only give them as numbers, but you can actually give them as distributions. So, what are we seeing here? This is normc, it stands for a normal distribution with cut-offs. So, as you know, a normal distribution, it goes to infinity on both sides, which is not what we want with a battery charge level because, well, they are physically constraints on both ends. They have a minimum and maximum charge. And this is what we do here as well. So, we set the mean of the distribution and the standard deviation, and then we define the minimum charge level and the maximum charge level, where this larger number is actually the maximum capacity of the battery, the default capacity of these vehicles when you give them a battery device. So, when we do this, let's actually look at the simulation. When you do this, we are now in the last folder, when you do this, you have your cars, and this time notice that we are coloring them according to the charge level. And the green cars and the blue ones, they're all good, they have enough charge left, but those ones where they go into the red and even into the grayish white thing, they're running on fumes, so to speak. Well, they would be if they were running on gasoline. In this case, they're running out of charge, basically. And notice how we even get this warning message here. In the line, it says, battery of vehicle so-and-so was depleted at a time. So, this poor guy here, they ran out of charge in the middle of nowhere, or rather in the middle of Berlin, which is a bad thing to run out of charge at. So, yeah, we certainly have to fix this or our future will be less bright with cars breaking down all over the place. But first off, I wanted to give you this little detail to see how you can actually color your cars by battery charge because you may not have seen it before. So, again, here in the vehicle configuration tab, we have all kinds of things to color the cars by. We have the speed, previously we had the trains colored by stop delay. If we want to look at the delay, not where they leave the stop, where they arrive, that would have been the stop arrival delay, but we can also color them according to some numerical parameter. This is this thing here. And then we get another box that we have to configure. And here, if you're lucky, you press this little arrow and you get a bunch of choices, parameters that the cars already have. But this is basically secret knowledge to know, well, it's documented, but it's not easily accessible here, to know that a car that has a battery device always has a parameter that's called device.battery.chargeLevel. So if you put that in there, you can color them according to this.

If you ever want to know what all these parameters are, well, there's a documentation page that I would like to show you, but we're offline. Well, actually, I can still show it to you because, as you probably know, SUMO always brings its documentation with it. So if you have an installation of SUMO, you always have a documentation of SUMO. So let's show where to find this. Somewhat halfway recent. So docs/userdoc, and there you have an index file somewhere. And now you have your offline documentation. So we go to TraCI and this is the problem with where do I actually click? No, actually, it might be a problem with the links in our offline documentation. So let's hope the next link works. Yes, this works, excellent. But the within page link seem to not work. But if you go to the value retrieval page of the vehicles, then you actually find at the very bottom a long, long list of parameters. And there's the charge level somewhere in this. So you can actually know what to look for. Also the taxi device has lots of fascinating parameters. All right. So always time to teach. Now, we wanted to change, we wanted to fix the problem of cars breaking down on the road. And I'm happy to tell you SUMO now has a feature to make this possible, developed by our colleague Mirko. It's the station finder device.

Electric Vehicles - Automated charging#

So this is a feature that lets cars automatically find a place to charge and then charge. Well, what are we missing before we can do this? We need the places to charge in our network. So let's go back and see how we actually get those. So back to the presentation. Actually go a few steps back. We want another configuration when building the network. So when we run, when we import the data from OpenStreetMap, we actually want to set this option here parking-output value="parking.add.xml", because when you want to charge, usually you have to leave the road and not obstruct it. So you need some, a parking area, first of all, before you can even think about charging.

Fortunately, OpenStreetMap brings this information. At the current state, with the latest release of SUMO, we reliably get the on-road parking area. So roadside parking actually. So not the, not the areas, the car parks that are really outside the road space, but rather the roadside parking. Be aware that this wasn't the case in previous releases. The simple reason being that the nice folks at OpenStreetMap deprecated a certain way of encoding this information. And we only discovered this a bit too late. So now we adapted to the recommended way of how these roadside parkings are captured in the database, and now it works again. So when you set this option, you will actually have something for your region most of the time. So let's look at a network that has roadside parking, just to see how that looks. No, actually, let's look at it like this. So we zoom in and we have these parking areas. So these are the blue, the blue sections. Each of those colored rectangles means this is a spot where cars can park. Red means it's not used. And if there were a car to park there, the rectangle would turn to green. Maybe we should switch the colors, actually. It's not really intuitive now that I think about it. OK, so these are the parking areas. But that's not enough. We need places to charge. For this, we do have a tool. It's called distribute charging stations. And you can find the script that calls this tool in the tutorial folder. Number five. But I'll just go with you over the configuration for this tool. So, of course, it needs a network. It also needs the parking spaces. We just import these. It needs to define where the charging stations go. And also it may have to cut into parts some of these parking areas. So actually we get a new output file for these as well. And then we just define a probability. We say 3% of the parking areas of the city, or rather of this region of the city, should get charging facilities with a certain charging power.

All the same, because we are building this out in one big go. This is the new infrastructure investment. Lots of money here. So we are just building this out at 3%. And then we have the infrastructure part down. So let's look at this. How does this infrastructure for charging look? And now we'll just draw all those places a bit larger. And you can see everywhere where there's a yellow C, there's a charging station. So when we zoom in, that's just another thing shown here. It's placed on the road, but it actually applies to the parking area. Maybe we should work on this visualization. Somebody taking notes? OK. Of course, there are facilities where you charge on the road. This is also one of these future scenarios. You just drive along. Maybe you're stopping your bus at the bus stop, or you're stopping in front of a traffic light, and you're being charged inductively a bit. So this is also something that can be done. But right now we want to just model charging that is attached to a parking area where you plug in the cable. So you see they are well distributed over Treptow-Köpenick, and now comes the Station Finder device, where we tell the cars that they may reroute to find a place to charge. So this is all things we can put directly into the SUMO configuration file. First of all, probability one. So every car is allowed to drive around and charge. Because we don't want to think about who does and who doesn't. Second thing, this is a more cosmetic thing. We say they can really run their battery down to zero. Maybe for technical reasons you wouldn't want to do this. Probably you wouldn't want to run it all to zero. But this warning about breaking down, it only comes when the battery is to zero. So for consistency, we're configuring this here not to be 5%, but really 0%. Then we're saying that if you're down to 10% of charge, you really need to think about charging again. The default is higher, but we don't want all the cars to run around charging, only some of them. So we're lowering this value, it's just a smaller scenario, it's for demo purposes. So in this case, we consciously deviate from something that might be reasonable. Also, there's a default of how far in time cars should look for a place to charge. The default is here set to 3 minutes. Not really sure where this comes from. Maybe it's an even further future where we have these stations everywhere, and we don't have to think about details too much. But I really had to raise this. Otherwise, cars wouldn't always find a charging station. We only set 3% after all. And then there is another option that says, when I plan how much charge I need to reach my destination, what is the margin of safety that I want to set? And the default is 10%. I found that in some places, this prediction wasn't robust enough. So I just increased this margin of error to 25%. This is probably something that we can improve on in the future. It mainly comes around when cars have to do an estimate, not after having driven for a while, where they could just take an average over the route so far. But if they just start, they don't have this average. In reality, the drivers would have it, of course, but we don't have it in the simulation. And then what we do is we have to look at the current road we're at and do an extrapolation to the future. And if the current road we're starting at is a slow road, and then later on we're driving on the motorway, then probably our estimate is a bit off. And so this larger margin of error helps in this scenario where we have both kinds of roads. And then the last thing that we're configuring here is how much do I want to charge before I end again. And the default is charge to 80% and then go on your merry way. But in this case, we would have many cars blocking the stations. We wouldn't have enough capacity to charge everyone. So I lowered this intentionally to reduce the time they stay there and charge and give some other guy the chance to charge as well. Now with all these things being said, let's look at the simulation. It's already open. So let's make the stations smaller and the cars larger. And let's have them drive. So you see some cars that are in the red, so to speak. But either they only have a short route, so it doesn't matter. They know that they'll manage to reach their destination or they go and take a detour and charge. Now from this, it's kind of hard to see who is doing what. And so it's easier to look at this in the simulation output and see how many cars actually changed their route. And then we still have a bit of time. We can follow it around and see at what time it actually did change. So let's run the simulation to the end. Something else that you could notice if you look closely is that the simulation is running slower right now. I clocked it to run about twice as long with the charging stations because all this extra routing and choosing where to charge, it does take some time to compute.

So let's look at the outputs that were generated. It's a file "tripinfos2" and another file called "vehroutes2". If we look at the first one, we get a bit of information about the battery and the nice thing is here everybody has depleted zero. So zero instances of running out of charge. You have to trust me on this because I'm not going through the whole file. And we have another thing, the routes. And most of the cars, well, they just follow the route. It's enough they started with enough charge. The distribution was lucky for them or they only had a short route. But if we go down, we find some instances of rerouting. We can actually search for this. Now I'm searching for the string "attime", and here we have these events. So at a certain time, the route was replaced. And we have a reason for that. The reason was "stationfinder:search". So the station finder device prompted this car to go someplace else and charge before continuing because the initial battery level was too low. So let's find the first car that does this. Looks to be this one. And then we'll just find this car in the simulation.

So we need to know its ID. And when it departed. 22.00. And now I'm doing something that might be useful to you as well. I want to run the simulation again, but I don't want to mess up my output files. If I run it now, the simulation starts writing again and all the files are overwritten. But I'm setting an output prefix. So this is just something that is prepended to all the written file names. So when I run the simulation now, the old files will be unchanged. And I'm writing to different files. And let's jump. What was the correct time? So this is our breakpoint. That's it. And now we can jump to the car. Lucky for you, we have all these hotkeys recorded. So I don't have to think about them too much. And here we have it. We have this car. And it has an initial route that goes there. But we know that at some time, later, the route was changed. To be precise, about two and a half minutes later. So let's follow this car around. And see what happens. We see the battery is already in the orange zone. So it's driving along. And there you have it. It decides to go somewhere else. Here. To this charging location here. And now let's track this car some more. So it's leaving the motorway. It's going to charge. You can see over the time, the color changes. And now it's charged to 30%. So you see it was almost at the destination. So here the reserve factor was very conservative. It would certainly have made it home. But not all cars would have. With the lower reserve factor. So some of those really needed charging. And to give you a bit more perspective on the charging taking place. I looked at the charging stations output. And I threw this in one of our visualization scripts. And here you see the number of cars charged at the different stations. So we had 53 charging stations overall in the network. 21 of them were used. Some were seeing very heavy use. And so you can do all kinds of analysis. Some scenarios of what if. What happens if I place my stations here. What happens if I increase or decrease the number of stations. And then you can build our bright future. Where we have electric cars everywhere. And they don't break down by running out of battery charge. Thank you very much.