Java Traffic Simulator (jts) is an agent based micro simulation on real transport networks. Designt for easy use. The project is relaized as part of the module: Project 1 at Bern University of Applied Sciences.
This project is currently under heavy developement.
- Easy but highly configurable with java properties
- Simulation of elements:
- Agents; moving parts of the simulation
- Lanes; where agents are moving on
- Edge; bundling lanes together.
- Junctions; connecting edges
- Networks; holding elements
- Import of open street map data
- Layered/parallelized simulation
- Independent simulation and drawing
- Simulation interpolation for smooth drawing
- GPS implementation with dijekstra
Table of Contents generated with DocToc
- Simulatable.java: Simulation engine which is easily extensible with new elements.
- Command.java: Integrated console engine with commands that are easy extensible.
- Command autodiscovery with reflection
- Thinkable.java: Easy interface for smart new agents.
- Importer.java: Import road map data from OpenStreetMap.
- Window.java: Graphical user interface with 2D output.
- Allows scrolling and zooming
- Allows console input & selection of elements by clicking
- main()
- Loads configuration
- Simulates with thinking
- Keeps map of saved simulation states
// load configuration
initialization();
// load net from xml files
loadNet();
// load agent routes & traffic flows
loadRoutes();
// app run
showWindow();
loop {
// remove agents which reached their target
checkRemoveAgents();
// spawn new agents according to routs & flows
spawnAgents();
// simulate all the layers
foreach( layer : layers ){
foreach in parallel( simulatable : layer ){
simulatable.simulate()
}
}
// give the thinkables some time to make decisions
foreach( thinkable : elements) {
thinkable.think();
}
// add simulation state to the list of saved states
addSimulationState( deepCopy( this ) );
}
end();
Maybe the biggest decision in the beginning of our project was how to model the road network. The first input cam from our supervisor and was the approach of using a skip list to model a lane. The index should represent the position in meters on the lane.
We decided to model not only straight roads with multiple lanes but also junctions to realize more complex road networks. We oriented us on the road network data format of the SUMO simulator. Therefore our basic domain objects were net, edge, junction, lane and agent.
Jts is structured in layers. The class which keeps track of them is Layers.java. Its usage is shown below.
- Net stores two different layering objects
- renderables : used for rendering
- simulatables : used for simulation
- Net adds elements based on their implementing interfaces (Renderable, Simulatable) to the layers.
- RenderPanel gets the layering object from Net (instance: wall clock) by calling getRenderables().
- Simulation gets the layering object from Net (instance: simulation time) by calling getSimulatables().
- RenderPanel and Simulation delegate execution to all the elements in layering order. See code taken from Simulation.simulate() as example below.
- SortedSet in Layers ensures total order according to natural order (for Integer '<') of layerKeys.
- .parallel().foreach() runs lambda-function in parallel, see Multithreading.
// delegate simulation to @{link Simulatable}s
final Layers<Simulatable> simulatables = simulateNet.getSimulatable();
for (final int layer : simulatables.getLayersIterator()) {
simulatables.getLayerStream(layer).parallel().forEach(e -> {
e.simulate(duration);
});
}
The parallelization paradigm is: Every simulatabe (s) with layer (l) is only allowed to change element states of simulatables (s2) if s2.l < s.l or s2 == s. This allows parallel simulation of all the simulatables in one layer. Due to the simple fact that there is no way java to enforce the paradigm we had to be very careful when writing new code.
All known simulation layers and residing classes.
- Agent
- apply agent decision
- update agent pysics
- Lane
- update position of agents in lane datastructure
- do collisions of agent on lane
- Edge
- switch agents between lanes on this edge
- Junction
- select agent for despawning
- reroute agents between edges
- Net
- agent spawning
- agent despawning
All knownt rendering layers and residig classes.
- Junction
- Fill gap between edges
In jts we heavily use the with java 8 newly introduces streams. The parallel() method in conjunction with lambda function are particularly useful for multithreading. The jre regulates instantiation of worker threads automagically and does quite a good job in scheduling work for all the workers as they are all more or less under the same load.
- green: running
- orange: park
GPS implements a working dijekstra algorithm for Net. The interfaces DirectedGraphVertex and DirectedGraphEdge make the dijekstra impelemntation independent from the data classes.
- GPS does most of the computation during construction.
- Once created GPS can not be adapted to learn an other Net.
- Due to the generic nature of DirectedGraphVertex and DirectedGraphEdge any dataclass could becose a component of a graph.
- Junction uses GPS for routing Agents to edges.
The actual simulation of the Net advances in discrete quantities of time. Meanwhile the Window advances according to the time the user experiences in real life. Those two components are decoupled with the getWallClockSimulationState() method in Simulation
We tried to implement an artificial intelligence that could master to drive on a arbitrary road network without causing a lot of collisions.
The agent has to make three kinds of decisions:
- How much to accelerate/deccelerate?
- Switch lane? When yes: left or right?
- Which turning to take on a junction?
For the acceleration we calculated a security distance, so that no collision would happen, if the agent ahead would fully break. This would work perfectly, if there are no lane changes and no junctions. But this two circumstances made things complicated. We didn't solve this problem through the lack of time.
The idea behind the lane switching decision was the following: An agent tries to drive on the rightest lane of a track whenever this is possible. If he has to slow down, because the agent ahead is too slow, his impatience increases. If the impatience reaches a specified threshold, the agent tries to switch lane to the left to overtake the slow agent ahead. One consequence of this behavior was, that the agents switched to the motorway access road in the ramp scenario. This problem could be solved if we would type the lanes (default, fast lane, motorway access road and so on).
For the turning decision we decided to provide the agent a "GPS" function. The route was then given by the spawning point and the destination. Both informations were given by the routes file. The GPS function was realized with an implementation of the Dijkstra algorithm.
Enteee, winki
- Write requirements doc
Enteee
- Basic simulator setup
winki
- Projekt setup
- Basic data structure
- Implement xml importer
Enteee
- Simulation (Decision objects, think, simulate)
- call every think method of all Intelligents (parallel)
- fill a collection
- loop through decisions -> simulate every decision (serial), without lane switching
winki
- Spawn agents
- Dummy AI
- Move agents
Enteee
- Zooming
- Collisions
- Lane switching
winki
- Render agents on polygons
- Orientation of agents visible
Enteee
- GPS-helper
winki
- Import of route-files
- Spawning of agents based on activities
Enteee
- Commands to element redirection
winki
- Embedded console, thread-safe
- Spawn and time commands for console
Enteee
- GPS unit tests
- Smarter agent, empty
winki
Enteee
- Draw simulation decoupling
- Bugfix lane set agent override
winki
- Simple map for developing agent
- Fix index out of bounds bug in polyshape class
- Realistic agent
Enteee
- Draw fake laneswitch
- Extended render interface with simulationStates
winki
- Improvement of realistic agent
Enteee
- Fixed interval simulation
- Dynamic app sleeping
winki
- Bugfix in lane
- Lane switching logic of realisitc agent
- Implementation of traffic flows
- Agent type can be configured in the routes xml file
- Despawning of agents when spawn info of type "Flow"
- Added restart command to console
Enteee
- Bugfix time conversion 10E-9 -> 1E-9 for nano
- Wall clock time in Window introduced
- Wall clock / simulation time decoupling -> issue lag
- Restart command fixing
- singleton app / window
- reflection for command finding
- toggleInterpolate command added
winki
- Added "ramp" net -> error at junctions
- Console can receive parameters from clickable GUI
Enteee
winki
- Every element has a position and can be located
- RealisitcAgent uses GPS
Enteee
- Simulation lag -> fixed with average velocity
winki
- Spawning and despawning only at junctions. Edges will be mapped to begin junction or end junction at importing time of the routes file
- Bugfix in RealisticAgent
Enteee
winki
- Bugfix (invalid relative positions)
- Agents can set turning (short-term decision) or destination (long-term decision)
- Console bugfix (command argument variables must not be final!)
- Help text for commands
- Added remove command
Enteee
winki
Enteee
- Advanced langechange
- Config stuff review
- Fixing collisions
winki
- Record statistics data (space mean speed, time mean speed, density)
- Comments, refactoring
- Configuration file
- Lane statistic values
Enteee
- Readme goes documentation
- Refactoring clicking
- Jcommander bug workaround
- Info command
- Agent despawning on no junction cross
- Refactor element removal -> Advanced removal (elements)
winki
- Bugfixes
- Transcendent agents when collision happend
- Agent handling on junctions
- RealsticAgents not looking beyond edge boundaries
- Area restricted tick method
- Weather / daylight
- Console command to import OpenStreetMap data
- Project outline
- Simulation of Urban MObility (SUMO), website
- Simulation of Urban MObility (SUMO), wiki
- Simulation of Urban MObility (SUMO), old website
- Traffic flow (Wikipedia)
This software and the underlying source code is licensed under the MIT license.