CitiesSkylinesMods / TMPE

Cities: Skylines Traffic Manager: President Edition
https://steamcommunity.com/sharedfiles/filedetails/?id=1637663252
MIT License
576 stars 85 forks source link

Traffic lights - green wave #278

Open originalfoo opened 5 years ago

originalfoo commented 5 years ago

https://en.wikipedia.org/wiki/Green_wave

GreenWave

brunoais commented 5 years ago

This is really quite useful if it can be done automatically. I've spent quite some hours trying to do this for the largest avenues to send the traffic away. So much satisfaction to be able to do the waves.....

originalfoo commented 5 years ago

Tagging #8

s2500111 commented 5 years ago

Even while there are some examples of green waves in real life, there are some things you need to think about, that will make this really, really complicated, especially, that they are hard to implement on bidirectional roads.

Furthermore this would probably distract from real traffic problems, since the only real use of a green wave is the shorter traveltime for an individual car, but not an increased throughput for the intersections as a whole. It's the opposite. Often abandoning a green wave is a solution for increasing capacity on heavily used roads.

So, as long as you're not planning a 70's car friendly city, there would be other features, that are far more helpful for managing traffic in the game.

brunoais commented 5 years ago

My idea for green waves is meant for one-way roads. Maybe even roads that work like giant rondabouts with many intersections over 20-30 segments.

originalfoo commented 5 years ago

there would be other features, that are far more helpful for managing traffic in the game.

Could you provide some examples?

s2500111 commented 5 years ago

From my experience, even some YouTubers are struggling to set up traffic lights in a correct way.

So at first I would propose to give some templates like a four way intersection with protected or separated left turns and three way junctions with effective layouts. The second thing is, that some of the descriptions are really unclear, especially when it comes to the different modes of when the light is switching. This could be clearer.

And a real feature could be a priority phase for a bus or tram lane, that kicks in as soon as a PT-Vehicle comes close, independently from the cycle of the rest. This is something that often kills green waves in cities but it can really speed up the public transport.

originalfoo commented 5 years ago

@s2500111 I also struggle to use the timed traffic lights tool, I'm keen to see a major overhaul of that feature of the mod. We've been tinkering with some ideas around better default traffic light set up based around conflict point mitigation - see #5 for details. It will be a while because we've got to get the Harmony update finished (TM:PE v11.0) and then overcome some issues with the updated overlay rendering before we can start progressing towards better traffic lights.

brunoais commented 5 years ago

I've adapted quite well to the timed traffic lights UI. No struggles at all. My only issue is how long it takes to properly setup. For example, it would be great to be able to set it up quicker. #5 seems to be a great step forwards to have an auto-setup that can then be optimized by the player

s2500111 commented 5 years ago

It's not that I'm personal affected, but that I've seen others struggling with the Interface.

I'm only struggeling with understanding the options for phase switching. The texts are a bit unclear.

originalfoo commented 5 years ago

I'll see if we can get the text improved at some point. I too find it a bit confusing and have to keep going to the wiki page to get a clearer idea of what it's doing.

kianzarrin commented 5 years ago

related to #540

kianzarrin commented 4 years ago

@aubergine10 I can understand how does green-wave work on a oneway road. but how do you make it work on a two way road? you can have green wave for one side or the other.

brunoais commented 4 years ago

On two-way road, green waves can work but it's very tricky because you need not only to move the wave but also the wave timing so that the simultaneous red light happens at different times around the cycles and vehicles have to wait much longer too. This applies to far side traffic lights only, ofc.

The more common and the choice I'd expect is to just wave in one direction and make the other direction counter-wave.

originalfoo commented 4 years ago

@kianzarrin for 2 way road it would have to assume that during green wave there is no far-side turns taking place maybe? Far-side turns could proceed once the green wave has stopped. The main goal is to allow traffic to progress along the arterial route more smoothly, assuming the bulk of traffic wants to go straight ahead.

originalfoo commented 4 years ago

I think before we even consider implementing this we should think of how to signal between junctions. Essentially treat roads as data cables between the traffic lights or something. That way we'd have the infrastructure to do all sorts of other cool stuff (particularly with level crossings maybe).

kianzarrin commented 4 years ago

@aubergine10 I think before we even consider implementing this we should think of how to signal between junctions. Essentially treat roads as data cables between the traffic lights or something. That way we'd have the infrastructure to do all sorts of other cool stuff (particularly with level crossings maybe).

Oh so you are talking about turning normal traffic lights into green wave. I thought we are talking about TTL.

for 2 way road it would have to assume that during green wave there is no far-side turns taking place maybe? Far-side turns could proceed once the green wave has stopped. The main goal is to allow traffic to progress along the arterial route more smoothly, assuming the bulk of traffic wants to go straight ahead.

Lets assume that there is no far side turn. my problem is that that you turn green light for both sides together. With this requirment if you have green-wave for one side then you will have red-wave (!!!) for the other side.

The more common and the choice I'd expect is to just wave in one direction and make the other direction counter-wave.

@brunoais The more common and the choice I'd expect is to just wave in one direction and make the other direction counter-wave.

is counter-wave the same thing as the red-wave I mentioned above?

kianzarrin commented 4 years ago

Myabe greenwave can work if we have symmetry:

s2500111 commented 4 years ago

Mhh, I think I can add some things to this discussion:

As I mentioned before, green waves are sounding far better then they actually are. While they are sometimes necessary on traffic lights with short distances as those are directly influencing each others capacity, their purpose on bigger distances is mostly to increase the average speed of cars. As they need fixed green times, they might even decrease the capacity. Implementing those is a engineering art work, as there are many possible problems. Here's the list from the German Wikipedia article on green waves, I'm trying my best to summarize them in English:

As a result, building a green wave is really complicated and it will bind a lot of resources to program this. Especially in two directions, which is often outright impossible (a thing you're seeming to figure out in this discussion). IRL green waves are often implemented in one direction in the morning and in another in afternoon, so that the direction with more traffic will get priority.

But I won't be all negative. There's probably a way to implement a sort-of-green-wave which is far easier then figuring out all the mathematics behind this: self-controlled traffic lights. The sad thing about these is, that they are a concept from a person in my city and most of his publications are in German. But some of his stuff, especially the general description, are also available in English und this link. Might be though, that there are similar concepts in English publications.

The best thing about them is, that they shouldn't need any completely new features. There's no need for direct communication between traffic lights, as this type of traffic light is using incoming vehicles as metric, which are also already used by timed traffic light in the game. It should be really close to actual timed traffic lights, with the most notable difference, that the phases are not organized in a linear order, but rather shuffled around to make the most of them. If a bunch of cars are incoming from a certain direction, they'll should get a green light and create their own green wave, without affecting the capacity of the system.

I'm not into programming mods yet, but if someone explains the basics to me, I could try to implement something like that. I'm just lacking the motivation to read guides for that in the moment ...

Another simple helping feature could be to show the travel time between two intersections, so it becomes easier to stack some static phases by yourself.

brunoais commented 4 years ago

Lets assume that there is no far side turn. my problem is that that you turn green light for both sides together. With this requirment if you have green-wave for one side then you will have red-wave (!!!) for the other side.

In this case, it's the same as having two roads next to one another. It's just that they are just part of a 2-way road.

is counter-wave the same thing as the red-wave I mentioned above?

Yes.

all traffic lights are the same distance apart.

Actually, no need. You need to know instead:

  1. Average vehicle acceleration for the road.
  2. Maximum speed allowed for the road.
  3. Game distance between intersections (not node count. Actual distance).

You can also try to cheat and, instead, just turn green and back to red based on how many cars in a road near an intersection but then it's not really a green wave, is it?

s2500111 commented 4 years ago

You can also try to cheat and, instead, just turn green and back to red based on how many cars in a road near an intersection but then it's not really a green wave, is it?

That's not cheating but an improvement upon the concept of a static green wave leading to increased capacity and decreased waiting times. Should also be way less complicated to implement, as I mentioned above.

originalfoo commented 4 years ago

Oh so you are talking about turning normal traffic lights into green wave. I thought we are talking about TTL.

I was talking about TTL, although it would be cool to integrate with normal lights too.

IRL green waves are often implemented in one direction in the morning and in another in afternoon, so that the direction with more traffic will get priority.

I love this idea and, as a user of Real Time mod, I would actually benefit from that due to transit patterns during shift changes. I'm not sure it would be much use without Real Time mod, however, as vanilla game doesn't really care about time of day for the most part (maybe a little change in evening if you have After Dark DLC, but even then barely noticeable).

We have a collection of things that could be time-related: https://github.com/CitiesSkylinesMods/TMPE/milestone/11


Also, green waves aren't necessarily just for vehicles, and they aren't necessarily just straight lines down a route.

Example: Level crossings across a few roads in a city or village. When the train approaches, you want the level crossings to be getting ready in-advance of the train, closing thier barriers. But you also want them to clear a path for cars that are currently crossing the tracks to escape to safety - thus there are two green waves happening:

  1. A green wave down the train track so the train doesn't need to slow
  2. A green wave on exit routes from level crossings to ensure cars can safely exit the crossings

This is why I feel we need some sort of event system so that one set of lights can "ping" nearby lights so that they can co-ordinate in a more manageable way.

With current TTL, you have to arrange all the steps of the lights together, which is impractical. It would be good if steps were though of more as "states" rather than a rigid sequence of steps.

With states you could do things like discussed above such as self-controlled traffic lights - the user could define their states and then define (if necessary?) what triggers a given state.

Example: User has created a priority route so the junction knows which segments are most important (priority signs) to keep traffic flowing; it also knows the medium importance (yield signs) and least important (stop signs). It knows which states give flow to which segments, so it can choose relevant state depending on traffic.

The green wave would then be just additional prompts to that system, based on signals from other lights. So a signal B from junction 4 could buff/nerf some states at junctions 3 and 5, or even set urgent priority for a given state.

Extending this further you can then do things where train travelling down track will send signal to next level crossing (distance of signal is dependent on train speed vs. distance to crossing maybe?) so they level crossing can start preparing to close it's barrier; the crossing would itself then send signals allowing nearby traffic lights to change, if necessary, so traffic can more easily leave the crossing.

Another example: An fire engine is responding to emergency; it sends signal down it's route "give me a clear path" - traffic lights start switching to states that a) increase chance of green light for fire engine and b) facilitate traffic that's trying to leave the route to do so and c) avoid allowing new traffic to enter the route.

A final example, is where there are light-controlled junctions in close proximity - in particular multiple level crossings, see: #11

s2500111 commented 4 years ago

With states you could do things like discussed above such as self-controlled traffic lights - the user could define their states and then define (if necessary?) what triggers a given state.

This is is a thing I'm dreaming of since a long time.

Another example: An fire engine is responding to emergency; it sends signal down it's route "give me a clear path" - traffic lights start switching to states that a) increase chance of green light for fire engine and b) facilitate traffic that's trying to leave the route to do so and c) avoid allowing new traffic to enter the route.

This is a nice use case. Look into how traffic becomes weights (cars have a weight of 1, busses something around 15 to prioritize them, trams even more to give them a clear path) you could also adjust the weight of an emergency vehicle to something absurdly high so the traffic lights are basically clearing all traffic from the road and also stop any inflow from other directions.

A short term goal could be to have this on single junctions, but a further implementation could be to trace the full path and clear the streets in advance. And at a last step you could fine tune it, so that the roads will be cleared only shortly before the emergency vehicle enters them.

A final example, is where there are light-controlled junctions in close proximity - in particular multiple level crossings, see: #11

At that point they are so close that you need to set up dependent lights. A flexible order of phases would allow for a state that clears the path, which would be triggered when a train approaches and never used as long as there is no train. I think that is different from a self controlled traffic light (more like a hard coded extra phase with a trigger then an intelligent thing, as the light normally wouldn't account for blockages behind it), but it should be easy to add, once out of order phases are a thing.


However, self controlled traffic lights shouldn't be to hard to create. They need:

The algorithm would then compare which phase has the highest weight and if there are some vehicles or pedestrians that need to move based on their weighting time and trigger the resulting phase.

Shouldn't be to complicated, as the amount of waiting/flowing vehicles is already a metric used in the current TTLs. Is it possible to decide between the different vehicle categories for the weighting?

It could also be interesting, how these numbers are accumulated. A more advanced step would be, to implement this in a way that vehicles are counted with a distance offset, so that a triggered phase change takes place when the vehicles arrive at the junction. Maybe I should really read the papers to this concept, to completely grasp how it's done ...

s2500111 commented 4 years ago

I found a survey over different methods of traffic light signalization. Currently, Timed traffic lights are actuated traffic lights, even though I feel like I've never understood the options on how the light decides to change phases. There's also a concept called self-controlled traffic lights, which is very similar to acuated traffic lights and has nothing to do with self-controlled traffic lights. Terminology, my old friend. However, they seem to completely miss the self-controlled idea. The most advanced technique they describe is the SCATS system, which seems to be far more complicated for achieving more or less the same result.

I think I'll try to figure out how the self-controlled lights work and try to share it with you. Maybe ask some of my traffic engineer friends for help to transfer those articles into some kinda algorithm.

On the other hand I looked into the code and uff, it's really a lot of code. So even when I try to fiddle as little with the UI as I could imagine it will take some time to wrap my head around this. On the other hand I got a successful build and found the code for timed traffic lights, so I might mess around with that and look if I get something done there.

originalfoo commented 4 years ago

The code in TMPE for traffic lights is pretty ancient, I think we could clean it up a lot, maybe even rewrite it.

I'm not sure we could do reinforcement learning with the limited CPU resource available (game already runs slow, and even slower with existing TMPE functionality).

s2500111 commented 4 years ago

One step at a time.

I think reinforcement learning is a bit overkill for this problem and is probably just a thing, because deep learning is a thing everywhere right now. Other then in other issues, I'm not seeing a a good reason for it, as traffic lights can be optimized to a good extend without it. The only thing I could imagine, is that the net will learn dynamic effects that are not easy calculable such as induced demand (drivers will avoid certain routes when they have to stop at every light or not take their car in general, if every other mode is faster) to optimize the network. Which is in turn rather useless as long as the traffic simulation is not simulating this. I also think that it's probably not only resource intensive on the cpu, but also on the development. Only option would be to use pre-trained networks which are limited to standard scenarios, so I'd cancel this option.

Do you know, how the used metrics are calculated? I will search for them in the code, but maybe you can answer that faster. Is it possible to change it in a way that different vehicles are weight differently? I could imagine to not only give busses a higher wait to improve public transport, but also weigh trucks heavier, as they require as much space as two or three cars. It's also possible in reality, so I would like to see it. Or is something like that already done?

s2500111 commented 4 years ago

So, after a long pause where I did not have time and nerves to look into this, I finally sat down and looked through the code, just to find, that it's completely uncommented and undocumented. So I would have to reverse engineer how the code works, to find out how to change a thing without just bricking the whole system. I can try this, but it will probably take months if I even get it done, as I'm probably struggling with my motivation for that.

So is here anyone who knows what the code does and is able and willing to write some kind of documentation for the timed traffic light code or is it abandoned and you all need to reverse engineer it too?

krzychu124 commented 4 years ago

Contact us on Discord chat, I don't remember everything, but I can quickly read and explain what it does. It's not that hard as you might think 😉

s2500111 commented 4 years ago

So here's a thing I could Imagine for the GUI (even though it will go through a replacement in the next time).

I'm trying to implement some traffic lights with fixed, synchronized cycle lengths, but it's really hard to create something within the spaghetti code that's creating the GUI. As mentioned in #8 the tool will be refactored in some time anyway, maybe expandability is getting better afterwards ...

I'm not really sure about the toolbar, as an accidental click could lead to problems there ...

GUI

s2500111 commented 3 years ago

I experimented a bit.

Even when you're giving multiple traffic lights the same cycle length, they're not the same length. Transitions seem to play a role, as they're non zero. On my search to find out how long a transition is, I found: bool ret = endTransitionStart != null && GetCurrentFrame() > endTransitionStart && stepDone;

So, two things to conclude from here.

  1. Transitions have no fixed time. This should be changed.
  2. As the simulation speed can vary quite a bit, traffic lights need to be resynced after a few seconds if they shall work together.

With the current model, a green wave is only possible if nodes are combined, otherwise the traffic lights will get out of sync after a while.

krzychu124 commented 3 years ago

As the simulation speed can vary quite a bit, traffic lights need to be resynced after a few seconds if they shall work together.

Could you elaborate?

s2500111 commented 3 years ago

Afaik the simulation is updated on a varying rate dependent on how much the CPU can put through. So in general the simulation for small cities ist much faster then for big cities. Correct me, if I'm wrong.

The Traffic lights are switched as soon as their time is over (assuming a fixed time) and a simulation step is done. So the actual green time of a traffic light is the stepTime + time until the next simulation step. Afterwards the light is yellow. The line bool ret = endTransitionStart != null && GetCurrentFrame() > endTransitionStart && stepDone; determines, whether the yellow phase is over or not. Should be at least taking around a second, since that seems to be the resolution of the GetCurrentFrame() function, but it's also not an exact second. So depending on circumstances, the lights have a full cycle length which can be described as:

_Tcycle = length of all steps + number of transitions + time between end of phase or transition and simulation step

We can determine the first two, but we can't determine the last one. Especially with different amounts of steps between lights, the last number may vary vastly between them, getting them out of phase with.

Or, to put it otherwise: every step takes a fraction of a second longer then it's set time. This adds up until we have a mess instead of a green wave. If we assume 4 simulation updates per second, the light might be off up to a full second after only 2 steps and 2 transitions, or exactly on expected time.

To solve this, we need an external clock determining which phase is the current one instead of the phases doing this for themselves.

So basically something like:

currentStepBegin = 5
currentStepEnd = 8

currentTime = GetCurrentFrame() % cycleLength 

if (currentStepBegin < currentTime < currentStepEnd){
    thisStep()
}

In this case, the inaccuracy wouldn't add up.

But it's completely incompatible with the current model, which is trying to make the steps more flexible and even be rearranged with fluctuating demand. If you put every minimum time to 0, it's basically a rough version of a self controlling light.

krzychu124 commented 3 years ago

Afaik the simulation is updated on a varying rate dependent on how much the CPU can put through. So in general the simulation for small cities is much faster then for big cities. Correct me, if I'm wrong.

Yes you are wrong :) Game simulation cannot skip frames, if you'll perform all calculations based on simulation frames it will be always 100% accurate. The thing with simulation speed up is that if your CPU can handle more frames that normally, you can unlock that ability so CPU will try do more simulation steps within. I wrote 'try', because simulation step is triggered by Unity FixedTime -> 64 ticks per second (sim speed 1x). If CPU is still processing last frame, FixedTime trigger will wait.

s2500111 commented 3 years ago

Ok, thanks. But is the calculation based on frames or is it just taking them for reference of time?

I'm still trying to wrap my head around how all this works. I observed, that traffic lights get out of sync, especially with differing amounts of phases within a few cycles, even when correcting for additional time in transitions. So the logical conclusion is, that there are some times I didn't think of.

Also, time is calculated from frame with >> 6 which should result in every frame being 64 ticks, so a second? But as the lower bytes are thrown out the window, we should get some ambiguity here, shouldn't we?