Walking and cycling legs
Walking and cycling appear in the model in two roles:
- as legs of a public transport journey: the pre-transport from the origin to the first stop and the post-transport from the last stop to the destination;
- as direct trips from origin to destination: the components
WW(walking) andCC(cycling).
This page describes how both are computed, step by step. The car is described on Private transport; how the legs are joined to the public transport chains, on Public transport.
Contents
- Step 1: the network
- Step 2: preparing the network
- Step 3: the leg stores
- Step 4: the leg types of the components
- Step 5: the direct walking and cycling trips
- Parameters
Step 1: the network
Walking
Walking uses the OSM network: the road segments that the OSM classification marks as pedestrian (IsPedestrian). The extract follows the reference date (AnalysisMoment): 20240524 for Y2015 to Y2024, 20260601 for Y2025 and Y2026. The model reads it from the network store %LocalDataProjDir%/OSM/Final_Network_<date>_r3.mmd, which it makes from the Geofabrik shapefiles (see Private transport, OSM). Every link can be walked in both directions.
Cycling
ModelParameters/Advanced/CyclingNetwork chooses the network for all cycling: cycling as pre- and post-transport, the OV-fiets, and the direct cycling trip.
With 'OSM', the default, the network consists of the OSM segments of the road types in the bike network (IsPartOfBikeNetwork, a BikeSpeed above 1 km/h), from the same extract as walking. Every link can be ridden in both directions, because the oneway of the Geofabrik shapefiles does not say whether cyclists are exempt.
With 'Fietsersbond', the network is the route network of the Fietsersbond, the network of 2024 delivered by PBL on 25 May 2025 (Fietsersbond_file_date), in %NetworkModel_Dir%/Infrastructuur/Fietsersbond_20250525. One delivery serves all reference dates. SourceData/Infrastructure/Fietsersbond/Network_Cycling turns it into a network with the attributes of the OSM bike network:
- It keeps the links with bicycle access (
toegangnot'geen') and two known nodes: 1,449,915 of the 1,771,242 links, 160,500 km. - A link with
toegang'heen'or'terug'(10% of the links) is a one-way cycle path: it can only be ridden in its direction of travel (IsOneDirection, with the geometry in that direction). - The 217 river ferries up to
Fietsersbond_MaxVeerpontLengte(2 km) take part, withFietsersbond_VeerpontExtraTijd(5 min) for waiting and crossing on top of the cycling time. The 62 longer crossings (2 to 39 km) do not. No origin, destination or stop is connected to a ferry. - The road type, used for the junction penalties, is
ferry,tertiary(cars above 30 km/h),residential(cars up to 30 km/h) orcycleway(cycle paths and pedestrian areas). - The topology is built from the end points of the segments, as for OSM, not from
van_idandnaar_id. - The network covers the Netherlands only, so there are no cycling legs to stops across the border.
With the Fietsersbond network the signature of the output names the network (Advanced/CyclingNetwork_FileTag, _fb20250525-veer2000m5min), and the output folder of a component that cycles gets _fb after its name (Advanced/CyclingNetwork_DirTag), for example 20251014_b2025_CC_fb. The output of both networks can so stand side by side; WW, W_PT_W and Car do not depend on the cycling network. The leg stores have the network in the hash of their name (see The store).
The two networks compare as follows (#124, at 14 km/h):
- 95% of the Fietsersbond network lies within 25 m of the OSM bike network. Most of the rest is in OSM under a road type outside the bike network (footways, pedestrian areas, tracks without a grade).
- 72% of the OSM bike network in the Netherlands lies near a Fietsersbond link; the rest is mainly
pathandservice. - For neighbourhood-to-neighbourhood trips up to 15 minutes the median ratio of the travel times is 1.000.
Speed
Every link has a constant speed: WalkingSpeed_kmhr (4.5 km/h) for walking and CyclingSpeed_kmhr (14 km/h) for cycling. An e-bike is a run with a higher cycling speed (Advanced/E_BikingSpeed_kmhr, 20 km/h). Measured speeds from the Fietstelweek (Advanced/UseActualCyclingSpeeds, OSM only) are used in the cycling travel time matrices for other analyses, not in the legs or the direct trips.
Step 2: preparing the network
PublicTransport_Prep/Create_Optimised_Network_Walking and Create_Optimised_Network_Cycling (Templates/CreateNetwork_Efficient_T) prepare one network per mode, which all leg types of that mode share:
- The origins, the destinations and the stops are connected to the network at the nearest connectable point (
connect). - Every junction a route passes costs time, a junction penalty, by the number of road links at the node: 0 s for 2 or fewer, 2 s for 3, 5 s for 4 and 6 s for more (
Advanced/Junction_Penalties, the same for walking and cycling). A junction where every road link is a slow-traffic road, a road type with a car speed of at most 30 km/h such as a residential street, a service road or a footway (Classifications/OSM/roadType/IsSlowTrafficRoad), costs nothing, because thewith_*_lowerSpeedLinks_*penalties are 0 s: in a residential area a walker or cyclist does not stop at every side street. Each link carries half of the penalty of each of its end nodes, so a route pays the penalty of a junction once. Only road links count, not the connection links of origins, destinations and stops. - Nodes that are not junctions are removed and their links merged into longer links; routes and travel times do not change (see Network optimisation).
Step 3: the leg stores
The base sets
All leg types are selections from four base sets, each computed once per reference date, origin set and destination set:
| Base set | From | To | Network | Store |
|---|---|---|---|---|
Org2Stops_Walking | every origin | every stop | walking | Legs_<Set>toStops_Walking_<hash>.parquet |
Org2Stops_Cycling | every origin | every stop | cycling | Legs_<Set>toStops_Cycling_<hash>.parquet |
Stops2Dest_Cycling | every stop | every destination | cycling | Legs_Stops2<Set>_Cycling_<hash>.parquet |
Stops2Dest_Walking | every stop | every destination | walking | Legs_Stops2<Set>_Walking_<hash>.parquet, only when the origin and destination sets differ |
When the origin set and the destination set are the same (PublicTransport_Prep/WalkingMirror), walking from a stop to a destination is read as the mirror of Org2Stops_Walking, because the walking network has no one-way links. Cycling has a store per direction, because the Fietsersbond network has one-way cycle paths (on the OSM network both directions give the same legs).
The computation
Per base set the model runs one Dijkstra over the whole prepared network (PublicTransport_Prep/TimeInvariantConnections/<base set>/Create_Routes, Templates/CreateNetwork_Pedestrian_Bike_T, with impedance_matrix_od64):
- from every origin (pre-transport) or every stop (post-transport);
- to every stop or every destination that is reachable;
- cut at the maximum time of the base set:
MaxWalkingTime_Org2Stops,MaxCyclingTime_Org2Stops,MaxCyclingTime_Stops2DestandMaxWalkingTime_Stops2Dest, 15 minutes each.
The time of a leg is its network time: the length of each link divided by the speed, plus the junction penalties.
The store
Each base set is a parquet file (zstd) in %LocalDataProjDir%/IntermediateResults, so that it can also be used outside the model:
- The columns are
BuurtCode(the CBS code of the neighbourhood),stop_idandstop_name(from the GTFS feed),Traveltime(the network time in minutes) andTravelDist(metres), as float64, so that the model reads them back exactly. - In the name,
<Set>is the origin or destination set (Advanced/OrgSet_NameTag,DestSet_NameTag, for exampleB2025),<hash>a hash of the signature. - The signature, in
<name>.signature.txtnext to the store, names the base set, the network and speed, the maximum time, the origin and destination sets, the reference date and feed, the numbers of places and stops, the format and the revision. The model reads a store only when its signature matches the settings of the run; otherwise it computes a new store, which has another hash and so stands next to the old one.
For 2025 (Buurt2025 to Buurt2025) the walking store is 5 MB and the two cycling stores 23 and 22 MB.
Generating the stores
- With
batch\UpdateAll.cmd legs: all base sets in oneGeoDmsRun, about 10 minutes per reference date and neighbourhood set. - In GeoDmsGui, under
/MakeUnlinkedData/LegStores: right-clickGenerate_All(all base sets), orOrg2Stops_Walking,Org2Stops_CyclingorStops2Dest_Cycling(one base set), and choose Update TreeItem; then reload the configuration (Alt+R). See step 3 of How to run the model.
The stores do not depend on the part of the day or the component. They need to be computed again after a change in the network (the OSM extract or CyclingNetwork), the walking or cycling speed, a maximum pre- or post-transport time, the origins, the destinations, or the stops (the feed and the reference date).
Step 4: the leg types of the components
Selection from the base sets
The pre- and post-transport type of a component (see Components and merging) reads the store of its base set (PublicTransport_Prep/Legs/<type>, template Legs_T) and keeps the legs to or from the stops of its stop set, within its own maximum time:
| Type | Code | Base set | Stops |
|---|---|---|---|
Org2Stops_Walking | W | Org2Stops_Walking | all |
Org2Stops_Cycling | C | Org2Stops_Cycling | all |
Org2RM_Stops_Cycling | C_RM | Org2Stops_Cycling | rail and metro |
Org2RMT_Stops_Cycling | C_RMT | Org2Stops_Cycling | rail, metro and tram |
Org2Ric_Stops_Cycling | C_Ric | Org2Stops_Cycling | InterCity stations |
Stops2Dest_Walking | W | Stops2Dest_Walking, or the mirror of Org2Stops_Walking | all |
Stops2Dest_Cycling | C | Stops2Dest_Cycling | all |
RM_Stops2Dest_Cycling | RM_C | Stops2Dest_Cycling | rail and metro |
RMT_Stops2Dest_Cycling | RMT_C | Stops2Dest_Cycling | rail, metro and tram |
OVF_Stops2Dest_Cycling | OVf_C | Stops2Dest_Cycling | stops near an OV-fiets location |
A selection gives the same legs as a Dijkstra of its own, because the route to a stop does not depend on which other stops are targets. The maximum time of a type may not exceed that of its base set (an integrity check of Legs_T).
Extra time
On reading, a leg gets fixed times on top of its network time:
- every cycling leg:
Cycling_StartTime(1 min); - a cycling pre-transport leg: also
Advanced/Cycling_PreTransport_Penalty(0 min), andCycling_ParkingTime_IC_Station(3 min) when it ends at an InterCity station.
The maximum times apply to the network time, as the cut of the Dijkstra does.
Price
- An OV-fiets leg (
OVf_C) costs the rental priceOVFiets_RentalPrice(4.45 euro). - Any other leg costs its time with the extra time, times the time costs of the mode:
PreTransport_Walking_Time_CostsandPostTransport_Walking_Time_Costs(0.19 euro per minute),PreTransport_Cycling_Time_CostsandPostTransport_Cycling_Time_Costs(0.09 euro per km atCyclingSpeed_kmhr).
The price of a leg always counts in Price_Augm. In Price it counts for cycling with Advanced/IncludeCyclingCostsInPrice (default TRUE) and for walking with Advanced/IncludeWalkingCostsInPrice (default FALSE).
Step 5: the direct walking and cycling trips
The components WW and CC are the direct trips (PublicTransport_Prep/Direct/Walking and Direct/Cycling):
- The route is a Dijkstra from every origin to every destination over the same network as the legs (
NetworkSetup/PrivateTransport/WalkingandCycling), up toMaxWalkingTime_Org2DestandMaxCyclingTime_Org2Dest(90 min). - The duration is the network time; for cycling plus
Cycling_StartTime. - The price is the time valuation
Direct_Walking_Time_CostsorDirect_Cycling_Time_CostswhenIncludeWalkingCostsInPriceorIncludeCyclingCostsInPriceis set, else 0. - The direct trips do not depend on the departure moment, so the components write one moment per origin block (the congestion moment of the part of the day,
07h30min the morning), computed in the output step (batch\UpdateAll.cmd outputwithComponent'WW'or'CC'). There is no intermediate store.
Parameters
| Parameter | Default | Description |
|---|---|---|
WalkingSpeed_kmhr, CyclingSpeed_kmhr | 4.5, 14 km/h | Speed on every link; in the signature of the leg stores. |
MaxWalkingTime_Org2Stops, MaxWalkingTime_Stops2Dest | 15 min | Maximum walking pre- and post-transport time; in the signature of the leg stores. |
MaxCyclingTime_Org2Stops, MaxCyclingTime_Stops2Dest | 15 min | Maximum cycling pre- and post-transport time of the base sets; in the signature of the leg stores. |
MaxCyclingTime_Org2RM_Stops, _Org2RMT_Stops, _Org2Ric_Stops, _RM_Stops2Dest, _RMT_Stops2Dest, _OVF_Stops2Dest | 15 min | Maximum time of the derived cycling types; at most that of the base set. |
MaxWalkingTime_Org2Dest, MaxCyclingTime_Org2Dest | 90 min | Maximum duration of a direct walking or cycling trip. |
Cycling_StartTime | 1 min | Added to every cycling leg and direct cycling trip. |
Cycling_ParkingTime_IC_Station, Advanced/Cycling_PreTransport_Penalty | 3, 0 min | Extra time at the end of a cycling pre-transport leg at an InterCity station, and at the end of every cycling pre-transport leg. |
OVFiets_RentalPrice | 4.45 euro | Price of an OV-fiets leg. |
PreTransport_*_Time_Costs, PostTransport_*_Time_Costs, Direct_*_Time_Costs | 0.19 euro/min (walking), 0.09 euro/km (cycling) | Time valuation of a leg or direct trip. |
Advanced/IncludeWalkingCostsInPrice, Advanced/IncludeCyclingCostsInPrice | FALSE, TRUE | Does the time valuation of walking or cycling count in Price? |
Advanced/CyclingNetwork | 'OSM' | 'OSM' or 'Fietsersbond'. |
Advanced/Fietsersbond_file_date, Fietsersbond_MaxVeerpontLengte, Fietsersbond_VeerpontExtraTijd | '20250525', 2 km, 5 min | The Fietsersbond delivery and its ferries. |