next up previous contents
Next: Some basics of object-oriented Previous: A do-it-yourself simulation package   Contents


Motivational start: Roundabout

In this chapter, we will consider the question if for an intersection it is better to have traffic lights or a roundabout. Our model is the simplest version that makes some sense.

The purpose of this chapter is to familiarize the reader with the general thinking that is used throughout this book: Models are started from simple first principles. In the following model, as in all models introduced in this book, the reader will easily detect imperfections. It is left to the curious reader (and programmer) to implement and test improvements.

We consider an intersection with four incoming/outgoing streets (Fig. 3). Streets are numbered 0, 1, 2, 3 as shown in the picture. We only model the incoming streets; as soon as vehicles leave the roundabout or the intersection, they have left our simulation world.

At each incoming streets, vehicles enter the simulation randomly but with a fixed rate. Each incoming vehicle selects any of the outgoing links as destination, excluding its own link.

Vehicles are moved forward along the link using the so-called cellular automata (CA) technique. This technique partitions space into cells which are updated via simple rules. In our situation, the street will consist of cells which are either empty, or occupied by exactly one vehicle. The system uses a parallel update (Fig. 3): All vehicles that have an empty cell in front of them at time $t$ can move one cell; the result is the configuration for time $t+1$. Vehicles at the end of the link can only continue when the traffic light is green, or when there is space on the roundabout.

Figure 3.1: (a) Schematic drawing. (b) Cellular automata driving logic. (c) The four traffic light phases.
[]
\includegraphics[width=\hsize]{gz/traffic1.eps.gz}
[]$\vdots$
$t$ = 10 sec
a   b c   d e  

$t$ = 11 sec
  a b   c d   e

$\vdots$ []\includegraphics[width=0.3\textwidth]{gz/traffic2.eps.gz}

The traffic light

The traffic light has four phases as indicated in Fig. 3. There are no ``yellow'' times between the phases (although they can be introduced easily). Vehicles can enter the intersection if the traffic light allows them to go into the direction desired by the vehicle. Otherwise, the vehicle will stop, blocking all other vehicles behind. Vehicles that are allowed to enter the intersection are removed from the simulation, that is, there is no interaction of vehicles inside or beyond the intersection.

The roundabout

[[need fig]]

The roundabout is modeled as a circular street, that is, it is a CA array of its own. Vehicles that leave the last array cell enter the first array cell. There are four entry cells into that circular array, corresponding to the four streets. A vehicle can enter when the entry cell and its upstream neighbor are empty. Vehicles leave one cell before the corresponding entry cell.




Implementation


Many possibilities exist to implement this, and experienced programmers will find there own system. The following paragraphs will provide some guidance, but they will not replace a programming class.

The programming style selected in this chapter is the most basic one we could think of. Later chapters will progressively introduce somewhat more advanced concepts.

CA links

The four CA links can be implemented as


{}
const double RATE=0.2 ;
const int LL=10 ;
const int NN=4 ;
int cells[LL][NN] ;
int tmpcells[LL][NN] ;
const int EMPTY=-1 ;
...
// go through time:
for ( int tt=0; tt<TT; tt++ ) {
    // go through all streets:
    for ( int nn=0; nn<NN; nn++ ) {
        // enter a vehicle if this is possible:
        if ( cells[0][nn] == EMPTY && drand48() < RATE ) {
            // select a number between 0 and NN-2:
            int destination = int( (double)(NN-1) * drand48() ) ;
            // if self is selected, use NN-1:
            if (destination==nn) { destination = NN-1 ; }
            tmpcells[0][nn] = destination ;
        }
        // go through all cells except last:
        for ( int ii=0; ii<LL-1; ii++ ) {
            if ( cells[ii][nn] != EMPTY && cells[ii+1][nn]==EMPTY ) {
                tmpcells[ii+1][nn] = cells[ii][nn] ;
            } else {
                tmpcells[ii][nn] = cells[ii][nn] ;
            }
        }
        // special treatment for last cell:
        if ( intersection_can_be_entered ) {
            move_vehicle_to_intersection ;
        }
    }
    // copy tmp array back to main array and clear tmp array:
    for ( int nn=0; nn<NN; nn++ ) {
        for ( int ii=0; ii<LL; ii++ ) {
            cells[ii][nn] = tmpcells[ii][nn] ;
            tmpcells[ii][nn] = EMPTY ;
        }
    }
}

Traffic signal

Again, there are many ways to implement this. Let us, for simplicity, assume that each of the NPHASES phases takes PP seconds; the phase is then given by


{}
for ( int tt=0; ... ) {
    int phase = (tt/PP) % NPHASES ;
}
where % is the C++ modulo operation. Let us then define a function


{}
bool allowed ( int from, int to, int phase )
which returns true when movement from link from to link to is allowed in phase phase, and false otherwise. Intersection movement can then be modeled as


{}
        // special treatment for last cell:
        if ( cells[LL-1][nn]!=EMPTY ) {
            int destination = cells[LL-1][nn] ;
            // if movement NOT allowed, keep vehicle:
            if ( !allowed( nn, destination, phase ) ) {
                tmpcells[LL-1][nn] = cells[LL-1][nn] ;
            }
        }

Roundabout

Implementation of the roundabout is left to the creativity of the reader. Note that there are some subtle timing issues involved: A reasonably clean implementation should not allow a vehicle to move two cells in a given time step; this would mean that a vehicle that just entered the roundabout is not allowed to make another move inside the roundabout. This can be achieved by first computing the tmpcells for all links, and only then copying them back to cells. In that way, a vehicle entering a roundabout would be copied into the tmpcells of the roundabout, where it would not be moved any further during the time step. Obviously, one has to be careful that no other vehicle overwrites this vehicle in tmpcells.

Output

Experienced programmers will have their preferred visualization toolkit. Here we just want to point out that, to a certain extent, it is possible to derive graphics from simple terminal operations. For example, links can be plotted by


{}
#include <iostream>
...
for ( int ii=0; ii<LL; ii++ ) {
    if ( cells[ii][nn] != EMPTY ) {
        // if there is a vehicle, output its destination:
        cout << cells[ii][nn] ;
    } else {
        // else output an empty space:
        cout << " " ;
    }
}
// Don't forget the newline once the link is plotted:
cout << endl ;

Most platforms have a so-called vt100 terminal; under unix this can often be obtained by typing setenv TERM vt100 in an xterm. For example, the command


{}
   cout << "\033[H\033[2J" ;
erases the screen, allowing the program to overwrite what was there before. This makes it possible to display the complete intersection dynamics as a movie inside a text terminal.

Variations

As said before, this is a very simplistic model, and many modifications of this are possible. Some examples:


next up previous contents
Next: Some basics of object-oriented Previous: A do-it-yourself simulation package   Contents
2004-02-02