Architecture - HY-OHTUPROJ-OSRM/osrm-project GitHub Wiki
Front-end
The routing-front repository contains the part of the software that the user interacts with. It allows the user to define polygonal roadblocks and speed zones on a map and find a route between any two points while taking the polygons into account. Editing and removing polygons is also supported. Map functionalities are based on the react-leaflet library, which makes the visualization of routes and polygons easy. The front end is done in React, making it possible to create polygons and routes on a one page principle.
The structure of the front end consists of the map, a form for routing, a list of the existing polygons and a form for adding a new polygon. The polygons, the start and end points of the route, as well as the route that was calculated between them are displayed on the map. On the top right corner of the map, there are buttons for drawing a new polygon, editing existing polygons and adding markers for the start and end points of the route. When the user draws a new polygon on the map, its coordinates will be automatically filled into the form. The list of polygons displays the name of each polygon and allows the user to delete them. The routing form allows entering precise coordinates for the start and end points instead of placing them on the map using the mouse.
Each polygon can be either a roadblock or a speed zone. Roadblocks completely prevent routing through them, while speed zones affect the speeds of the roads inside them. There are four different types of speed zones:
- Constant: All speeds are set to the given value
- Multiplier: All speeds are multiplied by the given value
- Offset: All speeds are adjusted by a fixed amount, either up or down
- Cap: All speeds above the given value are set to that value, other speeds are not affected
When multiple speed zones overlap, the one that gives the lowest speed is considered at each point.
Technical overview
Compared to the original front-end on osrm-project, the capabilities needed in this project require a lot more interaction between front-end and back-end. Also on front-end itself there are multiple values that need to be stored somewhere, such as edited zones. Therefore react is used to easily track when actions are complete between front-end and back-end, and when some actions are allowed and when not. The change to react from pure Javascript also enables the use of react-leaflet library, with ready made map functionalities. React-leaflet contains useful functions for objects added to the map, such as listening for user mouse actions, for example when they are hovering over certain objects, and what actions should take place when they do.
Due to the multiple values stored for each zone, such as its geometry, type, name and value, additional editing functionalities were needed. On editmode user can drag zone vertexes, but to change text values of each zone, another component had to be created. These text values are changed in a list component instead. This design decision lead up to the need of tracking a lot of information between components, so that if they are changed somewhere, they should also be updated in other places as well. To make this sharing of info easy, react redux was used, and a reducer slice has been created for most of the changing values, such as which polygon is user currently looking at, what is the current route and its start and end positions, and what are the defined zones.
The front-end is divided into 4 main folders, which are components, features, services and Utils. Components folder includes all the react components used in frontend. From these the map_Displayer.js is largest and handles all react-leaflet functionalities. This component also enables editmode, where user can easily create new zones or modify existing ones. When editmode is enable, the list component also goes into its own edit version, where each zone can be modified into new type of zone or change its current type's effect value. The modifications can be saved by pressing save button displayed on top right corner of the map. Another major component is the TimedAlert.js which enables informing the user if interactions between front-end and back-end succeed or fail. The component also contains a progressbar to inform user how long saving new zones will still take.
The features folder contains all reducers used in the application. These reducers are placed on their own corresponding folder for each reducer's type. These are messages, polygons, routes, segments and view. Messages contains timedAlertSlice, which enables creating and deleting alerts in any component at any time. polygon contains 2 slicers, one for editmode and one for viewing mode. These enable tracking changes made to polygons in either list component or map component and correspondingly update their values in the other one. Routes contains routeSlice, which is responsible of keeping in memory the current start and end positions, as well as the generated route. This way the route can be updated form any component in the application.
The services folder contains all functions related to calculating certain conditions being met or communicating with back-end. Services also contains some functions needed to approximate a polygon from a line, and extracting route geometry from received route data.
The utils folder is the smallest of folders and only contains some helper functionalities for dispatching to slices outside of react components, and config file for back-end url
OSRM
osrm-backend serves as the main routing engine. Since it supports blocking certain road segments using its osrm-contract
tool, no changes are needed to be done to the actual routing algorithm. When calling osrm-contract
, blocked road segments are given as pairs of IDs for their vertices.
To change weights of road segments for the purposes of routing while osrm-routed is running, the routing-api re-runs osrm-contract with --segment-speed-file and a csv file with segment speeds as documented in the link below, followed by executing osrm-datastore in order to update the routing data in osrm-routed shared memory segment. In order for this to work, osrm-routed must be run with --shared-memory and --algorithm ch.
Setting edge_speed_in_km_h in the segment speed file to 0 completely prevents osrm from routing through a road segment. This is how roadblocks are implemented in routing-api.
See OSRM project's documentation of the traffic feature here for more info.
Polygonal-Intersections
The Polygonal-Intersections repository contains a program for finding the road segments that intersect the given polygons. See the wiki page for more info.
API
The polygons and routes the user gives are sent to routing-api, where they were also received from at the start of the session. The interactions between the front end and the API are:
- The front end asks for a list of all polygons, and the API sends it
- The front end sends a list of added and deleted polygons, and the API replies with a status code
- When modifying a polygon, the old polygon is deleted and the new one is added
- The front end asks route between two points, and the API send it
The API is the central component of the software. When the user adds, modifies or deletes polygons, it makes the appropriate changes to the PostGIS database and calls osrm-contract
(a part of osrm-backend) to update traffic data for the affected road segments. When adding or modifying polygons, it finds those segments using the intersection algorithm. When the front end asks for a route between two points, it forwards the query to osrm-routed
(the HTTP interface of osrm-backend) and replies with the route data received from it.
PostGIS
The routing data in the PostGIS database consists of the output of the command osm2pgsql --slim
with route-data.osm (converted from Digiroad) as input, with the addition of a zones
table containing the polygon geometry for polygons. The schema is currently defined in the script create_database.sh. The polygon table uses the WGS 84 Web Mercator projection (SRID 3857) matching the Digiroad material.
Container structure
Polygonal-Intersections, osrm-backend and the API all run in the same container. PostGIS and routing-front both run in their own containers.