This special guest blog post by intern Devon Cowling. He is currently doing his final year project for his degree in Industrial Engineering at the University of Pretoria under the supervision of Jaco-Ben Vosloo. During the creation of his model, he encountered runaway congestion of vehicles (a massive gridlock) caused by blockages on intersections while using the AnyLogic Road Traffic Library. We hope that this blog post will provide others that experience similar problems with a potential solution.
Background
As a final year Industrial Engineering student at the University of Pretoria, one of our key deliverables is a project where we showcase our engineering skills. My project involves creating a traffic simulation of a neighborhood to test the impact on congestion when entrances to the neighborhood are closed or gated.
The road network for my model is also rather large and rather busy. About 6000 cars are going in and out of the neighborhood during the day. Due to the size and complexity of the road network, it would be an almost impossible task to explicitly create moveTo blocks for every section of the road network. Instead, we decided to keep the model logic super simple and use as few moveTo blocks as possible. One block will route an agent to the destination assigned to them, and one block will route the agent to exit the area once they have completed all their activities inside the area. With this design, we do not need to change any of the logic when the entrances are blocked dynamically. However, this choice meant that cars did not slow down and stop at the intersection stop lines and just continued at their speed until the destination was reached. Activating the yield function at intersections was not useful here, as adding a yield to all directions of an intersection seems to cancel each other out.
Below is a simplified version of the logic showing that all cars go through exactly the same logic blocks regardless of where they travel from.
Below is a picture of the neighborhood for which the flow of traffic is being simulated.
Problem
I discovered that the combination of the one moveTo block and busy roads means that intersections get dominated by the busiest direction of traffic as it does not stop flowing, and other cars often can't move into the intersection. This was unrealistic as the neighborhood I am simulating has stop signs at these intersections.
I needed some method of control over the intersections, preferably a stop sign. But in its current state, the road traffic library does not have a stop sign ability. I made a workaround for this by using traffic lights on short bursts - approximately 5 seconds- allowing you to send one car through every phase change.
Unfortunately, if the road network is busy as mine is, the standard traffic light becomes inefficient. This is because the vehicles do not have any knowledge of what is happening on the road after the intersection. With a standard traffic, light cars will try to move forward when the light turns green regardless of whether the road ahead is blocked by other vehicles. This behavior can again lead to blockages in the intersection and prevent cars from moving when their light turns green.
Solution
Just as I lost hope, I tried a last-ditch effort to seek help on the AnyLogic Software Users group on LinkedIn. You can click the link below to view the post.
I received very helpful advice from Benjamin Schumann, who I would like to thank.
He suggested writing code to check how many cars are upstream of the intersection before turning the light green. This led to the creation of the smart traffic light.
First, you need to create a traffic light manually for an intersection by using an event that changes the phase of the stop lines at the intersection.
This is necessary for the creation of the smart traffic light, but it can also be helpful when trying to reduce the number of blocks used in your model. The traffic light in the first image can be recreated with the event below, both will operate the same.
The next step is to add some code that will prevent cars from moving forward into the intersection if the road ahead is blocked. This can be done by using an if-statement to check how many cars are on the road ahead and keeping the light red if the road is full. The if-statement will look like this:
if(roadSegmentName.nCars(true) > x )
x is the limit for the number of cars on that road segment; determining this number will take some tinkering and will vary from road to road.
The true inside nCars tells the method to use the forward lane of the road, pick false if you want to evaluate the backward lane.
Below is the code for the smart traffic light. It checks the number of cars on road3, and if it is more than 3, all the lights will turn red for the roads leading to road3 but allow the cars leaving road3 to move.
if (trafficLightCounter % 4 == 0) {
if(road3.nCars(true) > 3 ) {
stopLine.setSignal(SIGNAL_RED);
stopLine1.setSignal(SIGNAL_RED);
stopLine2.setSignal(SIGNAL_RED);
stopLine3.setSignal(SIGNAL_GREEN);
} else {
stopLine.setSignal(SIGNAL_GREEN);
stopLine1.setSignal(SIGNAL_RED);
stopLine2.setSignal(SIGNAL_RED);
stopLine3.setSignal(SIGNAL_RED);
}
trafficLightCounter = 0;
} else if (trafficLightCounter % 4 == 1) {
if(road3.nCars(true) > 3 ) {
stopLine.setSignal(SIGNAL_RED);
stopLine1.setSignal(SIGNAL_RED);
stopLine2.setSignal(SIGNAL_RED);
stopLine3.setSignal(SIGNAL_GREEN);
} else {
stopLine.setSignal(SIGNAL_RED);
stopLine1.setSignal(SIGNAL_GREEN);
stopLine2.setSignal(SIGNAL_RED);
stopLine3.setSignal(SIGNAL_RED);
} else if (trafficLightCounter % 4 == 2)
if(road3.nCars(true) > 3 ) {
stopLine.setSignal(SIGNAL_RED);
stopLine1.setSignal(SIGNAL_RED);
stopLine2.setSignal(SIGNAL_RED);
stopLine3.setSignal(SIGNAL_GREEN);
} else {
stopLine.setSignal(SIGNAL_RED);
stopLine1.setSignal(SIGNAL_RED);
stopLine2.setSignal(SIGNAL_GREEN);
stopLine3.setSignal(SIGNAL_RED);
}
} else if (trafficLightCounter % 4 == 3) {
if(road3.nCars(true) > 3 ) {
stopLine.setSignal(SIGNAL_RED);
stopLine1.setSignal(SIGNAL_RED);
stopLine2.setSignal(SIGNAL_RED);
stopLine3.setSignal(SIGNAL_GREEN);
} else {
stopLine.setSignal(SIGNAL_RED);
stopLine1.setSignal(SIGNAL_RED);
stopLine2.setSignal(SIGNAL_RED);
stopLine3.setSignal(SIGNAL_GREEN);
}
}
trafficLightCounter++;
Each phase of the smart traffic light can check the same condition as above or different depending on where the cars are headed.
The smart light keeps the intersection open, allowing cars traveling in the opposite direction to move freely.
This approach will take some tinkering to set up correctly but will significantly improve the movement of vehicles in your AnyLogic traffic simulation. So next time you need to use a traffic light in AnyLogic, make it smart :)
Feel free to use the code above to create your own smart traffic light, or you can download the example model below or play with it on the AnyLogic cloud here.
Devon Cowling
Devon Cowling is a guest writer for the AnyLogic Modeler. Feel free to connect with him over LinkedIn.
What next?
If you liked this post, you are welcome to read more posts by following the links above to similar posts. Why not subscribe to our blog or follow us on any of the social media accounts for future updates? The links are in the Menu bar at the top, or the footer at the bottom. You can also join the mobile app here!
If you want to contact us for some advice, maybe a potential partnership or project or just to say "Hi!", feel free to get in touch here, and we will get back to you soon!