I have spent much of my coding life working on simulations of collective behavior. Usually this takes the form of large groups of birds or fish. This city traffic project developed out of a desire to try and simulate something more complicated than a traditional flocking sim. Whereas flocking animals calculate their trajectory by paying attention to neighbors, city traffic sims pay more attention to lanes and signals. Cars need to stay in their lanes, they need to pay attention to traffic signals, and they can only move if the space in front of them doesn't contain a car or red light. From there, you can start to design personality by adding variables like aggressiveness and reaction time which leads to a simulation that feels a bit more human than just dots following the prescribed paths of lane lines.
I wanted the setup to be simple. I should be able to draw (plausible) curves on the XZ plane, specify the number of lanes per curve, and the system would take care of the rest. The first step is easy enough: drop down a bunch of curves or straight lines. Obviously there are much more complex highway systems and intersection designs but I wanted to keep it simple for this execution. The system can handle non-right-angle intersections but if you make the angle too acute or oblique, you risk causing trouble down the line when its time to add vehicles.
Creating automatic intersections was a bit more challenging and took a couple failed attempts before I came up with a system that seems to work for most standard layouts.
The first step is to find all the intersection points for all the lanes as shown in the first image below. From these intersection points, I was able to determine which should be traffic signals by tracing each lane until it hit its first cross-street, setting that point as a signal, then skipping the next x points with x being the number of cross-street lanes minus one.
After I have found my signal points, I offset their positions along their respective lane to give the actual intersection some extra breathing room. For signal logic, I went with a fairly basic set of rules.
1) The light order is always Green - Yellow - Red - then loop.
2) There are no short turning lanes that appear near an intersection. Therefore, I simply state that if a road has more than 2 lanes per side, the inner-most lane is allowed to be a turning lane and its GYR light loop is offset to allow left turns without risking accidents.
3) If you are in the outermost lane, you have a chance of making a right turn (but currently no right on red).
4) If you are within 3 car lengths of a signal when it turns yellow, your aggressiveness determines whether you will run the red or stop.
5) You are able to make lane changes. If there isn't enough room, your aggressiveness will determine if you force your way in.
The cars in this simulation are convered in sensors. They pay attention to any obstacles that are in front or to the side, which included traffic signals. The car is aware of its speed, and combined with information about the friction of the surface, it can determine the safe braking speed. If the obstacle in front of the car begins to threaten the ability for the car to slow down safely, it will apply brakes.
In short, if the car has nothing in front of it, it will accelerate up to its top speed. If it is not stopped, it can change lanes or make a turn. If there is an obstacle or red light in front, apply the brakes.
There is so much more I want to do with this setup. Things on the to-do list include problem solving scenarios for grid-lock. As is, if two cars nearly collide forcing them to come to a stand still, they will stay in place forever. I want to work out a system where they are able to reverse a little and then find a path to get around each other.
Of course collisions are inevitable so I plan on hooking the sim up to a rigid body solver so if two cars do collide, something interesting happens.
The ultimate goal would be to throw a bunch of OSM roads at the sim and it would just work. Unfortunately, real-world intersections are much more convoluted than my system will allow. Check out this intersection by my office. Solving for all intersection possibilities would be a massive undertaking.