udsleeds / openinfra

Open access data for transport research: tools, modelling and simulation
https://udsleeds.github.io/openinfra/
Other
31 stars 4 forks source link

recode_highways fucntion #65

Closed hulsiejames closed 2 years ago

hulsiejames commented 2 years ago

Create function to recategorise OSM data.

Specifically, a function that recategorise highway data into one of the main classes of road that transport planners use. Much like this speed recategorisation function.

GretaTimaite commented 2 years ago

Could be used to replace my recategorization of speed in the inclusive_mobility function too.

hulsiejames commented 2 years ago

On road classifications, Chan and Cooper define the following table:

Road Class Description Selection from the OSM
7 Motorways highway = motorway OR highway = motorway_link
6 Non-residential Dual Carriageways highway =  trunk OR highway = trunk_link*manual classification needed
5 Residential Dual Carriageways highway =  trunk OR highway =  trunk_link*manual classification needed
4 Primary Roads highway =  primary OR highway =  primary_link OR (highway =  trunk AND oneway = F)
3 Secondary Roads highway =  secondary OR highway =  secondary_link
2 Tertiary Roads highway = tertiary OR highway = tertiary_link
1 Local Roads highway = living_street OR highway = residential OR highway = unclassified
0 Traffic-free Paths highway = cycleway

Cycling models require the simulation of motorised traffic in order to simulate traffic movement to be considered in cycling models for route planning (cyclists won't enjoy being on a busy road full of traffic!).

To model a given area for cycling, simulated motorised traffic must be modelled for an area 20x that of the cyclists, as zonal Origin Destination (OD) data is used for the entire car trip (~30km to a cyclists ~7km).

Accurately modelling motor traffic for such an area requires much more data, time, and money that required to model for cyclists, this becomes even more of an issue when comparing budgets for cyclist modelling and motorised traffic modelling.

Work above by Chan and Cooper propose estimating road traffic based on road classes, as defined in the table above, negating the requirement for the costly and time consuming modelling of motorised traffic.

The proposed method offers a large reduction in modelling effort, but nonetheless gives model correlation with actual cycling flows (R2 = 0.85) broadly comparable to a previous model with motorized traffic fully simulated (R2 = 0.78). Results show comparable performance albeit with substantially reduced modelling effort.


Also available is Guidance on Road Classification as (Motorways | A roads | B roads | classified unnumbered | unclassified)

Chan and Cooper actually consider the road classifications above and whether they capture sufficient detail of the urban environment:

Of particular concern was that A roads in the UK can be both major and minor arterials, and separately, be built with either single or dual carriageway design. Furthermore, the cycling characteristics of dual carriageway A roads differ substantially depending on whether or not they are fronted by residential properties.

On the above comment - Identical dual carriage ways, differing only by the fact that one is residentially fronted, have speed limits of (40mph - residential) and (70mph - non-residential)

To capture these differences to the cycling environment, we define three road classes extracted from A roads: residential single carriageway, residential dual carriageway and non-residential dual carriageway. The remainder of the Department for Transport’s classes were considered adequate for our purpose.

The definition of Chan and Coopers road classes in relation to the Guidance on Road Classification is shown in the table below:

Road Class Description General Definitions/Functions/Features Conversion to the UK Road Classification
7 Motorways(not included in cyclist model) Major road designated for regional connection, accommodating fast and high traffic flows. Central reservations used to safely separate high speed traffic flows. Other roads connect only at dedicated on/offramps allowing acceleration/deceleration. Cycling prohibited. Motorways (M)
6 Non-residential Dual Carriageways Major arterials forming a continuous route between two primary destinations. Central reservations used to safely separate high speed traffic flows. This road class locates outside residential areas with few connecting roads and no pedestrian sidewalks. A Roads
5 Residential Dual Carriageways Major arterials forming a continuous route between two primary destinations. Central reservations used to safely separate high traffic flows. This road class locates within residential areas with more connecting roads and pedestrian sidewalks. A Roads
4 Primary Roads Major arterials forming a continuous route between two primary destinations with lower capacity and speed than above-mentioned major arterials due to the design. A Roads
3 Secondary Roads Minor arterials which feed traffic between the major arterials and minor roads. B Roads
2 Tertiary Roads Minor roads which mainly collect traffic from local roads to arterials. Classified Unnumbered
1 Local Roads Local roads with high degree of access to residential properties and other trip endpoints. Unclassified
0 Traffic-free Paths Paths for use of cyclists and pedestrians only. N/A
hulsiejames commented 2 years ago

Could be used to replace my recategorization of speed in the inclusive_mobility function too.

As in could use the recode_maxspeed function with your IM function, specifically the # recategorize speed part? If so I can look into this!

Robinlovelace commented 2 years ago

This looks great. Looking forward to seeing the function emerge and committed, maybe in a new branch with associated PR ; )

hulsiejames commented 2 years ago

Given the above table on road class derivation it seems 5/6 will be linked and require manual classification (based on whether the A road is residential or not)

Want to look into whether we can use land_use= or distance to nearest residential building to be able to automatically specify between the two (5/6)

hulsiejames commented 2 years ago

I've produced a function that takes an sf frame of osm network and reclassifies road based on the table defined by Chan and Cooper.

I've uploaded a draft example vignette of the function to my static_host gh repo here. The vignette contains the function code along with a example using a Leeds dataset hosted on our releases, so the example is reproducible.

@Robinlovelace I will set up a PR to get the function file added to the repo.

You can see the current function below - any thoughts welcome!

``` Date 27/06/2022 Authour James Hulse Version 1.0.0 # Define recode_road_class function recode_road_class <- function(osm_sf) { library("dplyr") # Creates road_class column osm_recat = osm_sf %>% dplyr::mutate(road_class = dplyr::case_when( # (7) - Motorways highway %in% c("motorway", "motorway_link") ~ "7", # (6/5) - Dual Carriageways resi & non-resi highway %in% c("trunk", "trunk_link") ~ "6/5", # (4) - Primary Roads highway %in% c("primary", "primary_link") | (highway == "trunk" & oneway == "F") ~ "4", # (3) - Secondary Roads highway %in% c("secondary", "secondary_link") ~ "3", # (2) - Tertiary Roads highway %in% c("tertiary", "tertiary_link") ~ "2", # (1) - Local Roads highway %in% c("living_street", "residential", "unclassified") ~ "1", # (0) - Traffic-free Paths highway == "cycleway" ~ "0" )) %>% # Creates road_description columns dplyr::mutate(road_desc = dplyr::case_when( # (7) - Motorways highway %in% c("motorway", "motorway_link") ~ "Motorways", # (6/5) - Dual Carriageways resi & non-resi highway %in% c("trunk", "trunk_link") ~ "Dual Carriageways (R&NR)", # (4) - Primary Roads highway %in% c("primary", "primary_link") | (highway == "trunk" & oneway == "F") ~ "Primary Roads", # (3) - Secondary Roads highway %in% c("secondary", "secondary_link") ~ "Secondary Roads", # (2) - Tertiary Roads highway %in% c("tertiary", "tertiary_link") ~ "Tertiary Roads", # (1) - Local Roads highway %in% c("living_street", "residential", "unclassified") ~ "Residential / Local Roads", # (0) - Traffic-free Paths highway == "cycleway" ~ "Cycleway" )) %>% # Removes features that have not been recodeed to a road_class value filter(!is.na(road_class)) } ```
GretaTimaite commented 2 years ago

Great stuff @hulsiejames. Just please credit/cite the paper from which you drew the inspiration for the function. It might be useful if you add an introductory paragraph explaining why the function could be useful (you can refer to the paper here too).

Apologies if you've mentioned this in the vignette -- I've just skimmed it and will comment more on the code later, if needed (though it looks good).

hulsiejames commented 2 years ago

Thanks @GretaTimaite! Yup it's in there but admittedly not at the top!

Only a draft but as it looks good I'll add context para and proper paper context and maybe move over to OpenInfra once approved!

Robinlovelace commented 2 years ago

Very nice outputs James! See comments I've made in your PR. This will be a great function when it's up and running.

hulsiejames commented 2 years ago

I think this is complete now so will close.

Any issues / updates with the fucntion can be documented in a new issue.