movsim / traffic-simulation-de

Source code for javascript simulation of website
http://www.traffic-simulation.de
GNU General Public License v3.0
980 stars 143 forks source link

traffic-simulation.de

Source code for the interactive Javascript simulation at traffic-simulation.de

The simulations should be self-explaining and is also explained in the instruction boxes in most scenarios.

Besides simulating online, you can also use this simulator to generate vehicle trajectory files and virtual detector data files by using the blue download button (details further below).

Information on the used models and numerical integration schemes can be found in the links on the simulator page. In the following, I give some overview about the implementation.

Running the Simulation

This simulation uses JavaScript together with html5.

The master html file, for example onramp.html, starts the actual simulation by the canvas tag:

<canvas id="canvas_onramp" ... >some text for old browsers </canvas>

What to do with this canvas is specified in the init() procedure of onramp.js which starts the simulation and is assocoated with this canvas by the first command of the init procedure,

 canvas = document.getElementById("canvas_onramp");

(for ring.html, the init procedure of ring.js would be associated with the canvas of that file, and so on). At the end of the initialization, init() starts the actual simulation thread by the command

return setInterval(main_loop, 1000/fps);

The canvas dimensions are set/reset depending on the actual browser's viewport size by additional controls in canvasresize.js implementing a responsive design.

Note on cached data

If the simulation does not run, sometimes the cause is old code in cached javascript or css files. So, the first thing to do is empty the cache

Offline Usage

Just download the whole project (go to the Code button on the github project page, wait for the dropdown menu of Code to open and chose Download ZIP). After unpacking, load, e.g., index.html as a local file in your favourite browser.

Program Files and Structure

The javascript code uses pseudo objects in appropriately named files, particularly

\<scenario>.js (ring.js, onramp.js etc)

the top-level simulation code for the corresponding scenario called in ring.html, onramp.html etc. Initializes the road network elements needed for the corresponding scenario (e.g. mainroad and onramp for the onramp scenario), starts/stops the simulation, controls the simulation updates in each time step depending on the scenario, draws everything, and implements the user controls defined in _ringgui.js, _onrampgui.js etc.

\<scenario_gui>.js (ring_gui.js, etc.)

Defines the user control. Each simulation scenario (such as ring, onramp, roadworks) has both a top-level simulation javascript file \<scenario>.js, and an associated gui \<scenario>_gui.js (and of course an html file \<scenario>.html).

road.js

represents a directional logical road link as array element of the network variable defined in the top-level scenario files and organizes the vehicles on it. Contains an array of vehicles and methods to get the neighboring vehicles for a given vehicle, to update all vehicles for one time step, and to interact with/get information of neighboring road network elements.

It also has a unique roadID and provides methods to draw this network element and the vehicles on it. These drawing methods depend on the road geometry functions traj_x and traj_y giving the geo-located positions (x,y) as a function of the arclength u which are provided by the calling pseudoclasses \<scenario>.js at construction time. Further details for road.js and how to connect it with other roads are given further below.

vehicle.js

each vehicle represents a vehicle-driver unit and has (i) properties such as length, width, type, (ii) dynamic variables such as position and speed, and (iii) a (deep copied) instance of the acceleration/lane changing methods from models.js. Optionally, a vehicle has also a route as a sequence of roadIDs to be traversed. This is only needed in scenarios with off-ramps or intersections.

Each vehicle also has a data element driverfactor set at construction time to model inter-driver variations (see below).

Besides regular vehicles, there are also special vehicle objects to be identified by their vehicle ID:

models.js

a collection of pseudo-classes for the longitudinal models (presently, the IDM and an extension from it, the ACC model), and lane-changing decision models (presently, MOBIL), see the references section for details. In addition to the pure models, following features are implemented.

How to implement new models

This is now described at the beginning of models.js. Basically, the steps are

To help in implementing, I defined the global flag testNewModel in control_gui.js. If set to true, a new skeleton "CACC" model will be used which is essentially the IDM. To check if this really works, I set the desired speed for the truck template to 3 m/s (you will see slow trucks if this works as intended). So you need just change all locations where testNewModel is used and you are done for all simulations.

TrafficObjects.js

a set of traffic-related objects that can be dragged by the user from a "depot" to a network link (road) and back. The main data element of this class is an array trafficObj of the traffic objects. At present, any array element traffObj=trafficObj[i] can represent one of three types of traffic objects:

Any object has one of two states at any time specified by the object's data element isActive:

The traffic light and speed limit objects also have values:

The main unique component of the objects is its traffObj.id. In case of active traffic light or obstacle objects, the id of the generated vehicle objects on the road are the same as that of the traffObj and in the range 50-199 (all special vehicles have ids < 200). The complete list of traffObj and vehicle id ranges is as follows:

colormanip.js

Helper-class providing some speed and type-dependent color maps to draw the vehicles.

redirect.js

callback (implementation) of the buttons for the different scenarios on the \<scenario>.html simulation pages

Numerical Integration

The underlying car-following model for the longitudinal dynamics providing the accelerations (Intelligent-Driver Model, IDM, or extensions thereof) is time-continuous, so a numerical update scheme is necessary to get the speeds and positions of the vehicles as approximate integrals over the accelerations. For our purposes, it turned out that following ballistic scheme is most efficient in terms of computation load for a given precision. Its pseudo-code for an update of the speeds speed and positions pos over a fixed time interval dt reads

speed(t+dt)=speed(t)+acc(t)*dt,

pos(t+dt)=pos(t)+speed(t)dt+1/2acc(t)*dt^2,

where acc(t) is the acceleration calculated by the car-following model at the (old) time t.

Lane-changing is modelled by the discrete model MOBIL, so no integration is needed there. In order to reuse the accelerations needed by MOBIL (Minimizing Obstructions By Intelligent Lane-changes") for calculating the lane-changing decisions, lane changing is performed after evaluating all accelerations. Furthermore, since MOBIL anticipates the future situation, the actual speed and positional update is performed after the lane changing. Hence the central update sequence performed for all road instances of the simulated network is given by

  roadInstance.calcAccelerations();
  roadInstance.changeLanes();         
  roadInstance.updateSpeedPositions();

in the main simulation file of the given scenario (ring.js, onramp.js etc). The main method is either updateRing() (ring road), or updateU() (the other scenarios).

Graphics

The drawing is essentially based on images:

Download trajectory and virtual detector data

Besides just running the simulation interactively (should be self-explaining), you can also download the simulated trajectories and virtual detector readings

Using the download functionality

Once your favourite simulation is running, you can start recording by clicking on the blue "Start download" button to the left of the language flags. One you have stored enough data, click the same button which now reads "Finish download" and, after allowing downloading (depending on the OS, some message pops up), you can find your downloaded files in your standard Downloads folder. Depending on the number of road segments of the simulation, you have one or more trajectory data named

road<n>_time<starttime>.txt

and virtual detector data files named

Detector<name>_road<n>_x<pos>_time<starttime>.txt

Changing the sampling rates

The trajectory time interval is set by the variable dt_export; in gui.js (default value: 0.5 s). However, this does not give the realized timestep if the output time step is not a multiple of the simulation time interval dt_sim. Then, you will always get a varying multiple of dt_sim.

The simulation time interval, in turn, is dynamically set to realize fps=30, so we have dt_sim=timelapseFactor/fps. For the default time lapse of 6 (in most scenarios), we thus have a simulation time interval of 0.2 s.

To change the trajectory sampling time intervals, you need to do the following:

To change the stationary detector sampling interval, change the constructor call in the corresponding simulation:

...=new stationaryDetector(road,position,samplingInterval);

More detailled description for road.js

The most important data elements

The most important road functions/methods

Central simulation road update methods called at each time step dt

Each of the following methods acts on all vehicles and is called for all links of the network before going to the next. As a result, the order of the vehicles or links does not play a role in the update (parallel update)

The order of the updates

Generally, each of the following actions (if applicable) is executed for all roads and on all vehicles before going to the next action. So, a parallel update is ensured which is the only update type making sense in general networks without a natural order:

Intersections and connecting road network elements

This is realized by the method road.connect(target, uSource, uTarget, offsetLane, conflicts, options). When connecting just two network elements end-to-end (for example to model lane closing or opening or other changes of the road properties or right tuens where the only thing to watch are the vehicles on the target road but no crossing streams), conflicts=[]. Otherwise, the conflicts are analyzed by road.determineConflicts(..)

Connecting two roads end to end

Intersections for ODs with no conflicts

Example for a right-turn from the source road to the target road at the target coordinate uTurn:

sourceRoad.connect(targetRoad, sourceRoad.roadLen, uTurn, nLanesTarget-nLanesSource, [], maxspeed, targetPrio); The difference to the above is only the target u coordinate, the lane offset (the rightmost lane of the source, index nLanesSource-1 connects to the rightmost lane of the target, nLanesTarget-1, and the optional parameters maxspeed and targetPrio

Notice that, also with conflicts=[], the vehicles on the target road are always considered. In effect, a right turn to another road (or a general turn without conflicts) is a mergeDiverge with a single merging decision point instead of a finite ramp length. Therefore, much anticipation heuristics is needed unless one mandates an entry with a stop (maxspeed=0).

Notice not yet perfect

Intersections for ODs with conflicts

In most cases, crossing or turning at intersections does not only involve looking out for the traffic on the target road (this is done outside of the conflicts[] specification) but determining and resolving conflicts with traffic on roads that are neither source nor target: Following is for a classical non-signalized four-way intersections with all ODs (except for U-turns) allowed. Since OD restrictions are implemented on the basis of the allowed vehicle routes, these need not to be considered here. Some conflicts just do not appear if there are turning restrictions. Things get simpler for a T-intersection.

All this is done by the method road.determineConflicts(..) quite tricky, see the code.

References

[1] M. Treiber, A. Hennecke, and D. Helbing. Congested traffic states in empirical observations and microscopic simulations. Physical review E 62 1805-1824 (2000). Link, Preprint

[2] M. Treiber and A. Kesting. Traffic Flow Dynamics, Data, Models and Simulation. Springer 2013. Link

[3] A. Kesting, M. Treiber, and D. Helbing. General lane-changing model MOBIL for car-following models. Transportation Research Record, 86-94 (2007). Paper

[4] A. Kesting, M. Treiber, and D. Helbing. Enhanced intelligent driver model to access the impact of driving strategies on traffic capacity. Philosophical Transactions of the Royal Society A, 4585-4605 (2010). Preprint

[5] M. Treiber, and A. Kesting. An open-source microscopic traffic simulator. IEEE Intelligent Transportation Systems Magazine, 6-13 (2010). Preprint

[6] M. Treiber and V. Kanagaraj. Comparing Numerical Integration Schemes for Time-Continuous Car-Following Models Physica A: Statistical Mechanics and its Applications 419C, 183-195 DOI 10.1016/j.physa.2014.09.061 (2015). Preprint