Intersection with traffic lights in an AGV network
This model aims to showcase how allocations of control areas can be manually controlled to achieve more complex logic than the default “first come first serve” implementation.
It depicts a four-way road intersection with arriving cars being able to continue in any of the three other directions. Cars driving straight on or turning right use the right lane, cars turning left use the left lane and must give way to oncoming traffic.
Traffic lights manage which cars are allowed to enter the intersection at any given time.
AGV network and general concept
In order to understand the logic behind it, let’s first look at how the AGV network is setup. In the screenshot below we deactivated the visualization of the roads to show the paths and areas more clearly. For each of the four directions there are two incoming paths and one outgoing path. Control points (red) are placed on the incoming paths at the points where cars must stop (based on object center) when the light is red.
A single, large control area that control the entry is placed such that is encompasses the entire intersection. Within this control area, an additional control point is placed on each of the left turning paths (orange). This is the location where left turning vehicles must wait for the oncoming lane to be clear. To enforce this the four smaller, rectangular control areas are used. The lane turning left and both the straight and right turning lane coming from the other direction pass through one of these areas. We will later explain how the straight and right turning cars are given priority to allocate these areas, resulting in cars wanting to turn left having to wait until no other allocation requests are present. As all paths are one-way and the geometry is pretty simple, all things considered, the distance between cars is handled by an accumulation behaviour set on the paths.
The logic controlling the vehicles is very simple. If we zoom out, we can see that cars leaving the intersection in any direction eventually just turn around and return.
At the turning points control points are placed that serve as the travel destination for the cars. A Process Flow with one token per car randomly chooses the next destination when the previous travel task is finished and sends the car there.
The cars will automatically use the correct lanes, since those are the shortest paths to reach their destination. For the intersection logic each combination of origin and destination (meaning every possible way of crossing the intersection) is represented as a number. These numbers are stored as global macros for ease of use. The letters represent the four cardinal directions (north, west, south, east). For example, using the intersection to travel from east to west would be represented by the ‘mode’ number 4. At the same time as a new destination is chosen for the car, the respective mode number is also written to a label on the car.
In the logic that controls entries into the intersection, these modes are used to identify which vehicles are allowed to enter. Powers of two are used, so the numbers can simply be added together to get a single number that encodes which lights are green. The light phases are defined in a global table. One of the simplest sensible configurations is shown below. At first, all lights are red (no entries in the “Green” columns) for 5 seconds. Then all cars coming from the west and east directions receive a green light for 20 seconds. This is followed by another 5s of all red lights and finally the other directions are allowed to move on. The table is then repeated from the top. The phase in line two would be represented as mode 1365 (1 + 4 + 16 + 64 + 256 + 1024). This becomes a lot more obvious when the mode is written in binary: 0000 0101 0101 0101
Each bit represents one of the possible directions.
Allocation logic explained
The control area is set to allow 0 concurrent allocations. Meaning for a request to actually result in an allocation, we need to override the return value of the “On Request” event of the control area. This happens in the control logic for the intersection that is implemented as an Object Process Flow linked to the control area.
An Event-Triggered Source reacts to the On Request event and writes a reference to the “Allocator” (meaning the car/AGV) to a label on the token. Note that the “Will Override Return Value” box is checked. The token then enters a Finish activity in whose “Return Value” field the current traffic mode of the control area is compared to the mode of the requesting car. The “&” is the bitwise-and-operator. It goes through both numbers bit by bit. If the bit at a given position is 1 in both numbers, it will also be 1 in the returned value, 0 otherwise. If the mode of the car is part of the current traffic mode (which is a sum of such modes) the result will be the mode. This non-zero number is interpreted as “true” in the if-condition and the return value of the code is to allow the request to go through. Otherwise, the request is blocked. (The “Allow” and “Block” properties return 1 and -1, respectively.)
The second part of the Process Flow is a loop with a single token that reads the next traffic mode from the global table. It then ‘announces’ which phase the intersection will enter next, so that the draw logic of the traffic light objects can start the process of switching from red to green or vice versa if needed. After a delay, in which those lights would show yellow, the current phase of the control area is updated. The same code that updates the label then also searches for cars that are now allowed to enter the intersection among the pending allocation requests. Since, as far as I could tell, there is currently no direct method to refire an allocation request, those cars receive a pre-empting task sequence that uses a break task to immediately return to the previously active sequence. The restart of their travel task then causes them to try to allocate the control area again.
After waiting the duration assigned to the current traffic phase, the token once more updates the mode of the intersection to an ‘intermediate’ mode. This mode is the result of another bit-wise comparison of the current and the next mode. This allows lights that need to change to red to do so, while lights that stay green remain unchanged. Once the next phase is activated, additional lights might then become green.
If the next phase doesn’t have any green lights, all lights will already be red in the intermediate mode, meaning the Process Flow block that updates the mode can be skipped and the token instead just waits out the duration in the “All Red Duration” Delay activity.
The logic that makes left turning vehicles give way to oncoming traffic works in a similar way. It is also implemented as an Object Process Flow, linked to the four smaller control areas within the intersection. These areas allow a single allocation by default and also have a “Mode” label. But it’s not set based on a timer and otherwise static. Instead, these areas start in mode 0 and if a request is made while the area is empty, the allocation is always allowed, and the mode is set to match that of the allocator.
When another request is made, the areas mode is compared with that of the new requesting car. If they match, the request can potentially be granted. First however, the code searches other pending requests for a mode with a higher priority than that of the current request. (The mode numbers are assigned in the order straight < right turn < left turn, so they can also be used as a priority value, where lower is better.) If such a request is found, the current one is blocked, to allow for the area to empty. At that point, a token created by a source listening to the “On Deallocated” event of the control area will reset the mode of the area to 0 and sort any pending requests by priority, before those get re-evaluated.
In summary, this logic allows an arbitrary number of cars with the same mode to enter the area. As soon as a higher priority request that can’t immediately enter is created, other requests are blocked; they must ‘give way’.
Visualization and parameters
The traffic lights are BasicFR objects that draw colored circles as lights in their On Draw trigger, depending on a label. That label is updated in the On Message trigger whenever the intersection changes its phase.
The roads are drawn along the AGV paths in the On Draw code of a dummy object placed to the side of the intersection. How wide and in what interval the white lines are drawn is determined by Array labels on the paths containing all necessary parameters.
The model comes with five parameters: The first controls which table is used to determine the traffic light phases, the second and third set the time it takes a light to switch from red to green and green to red. The fourth sets the number of cars and the final one switches the visualization of the left turn lights to arrows.