From fa8044f3527a1e8e3d5395e4294ede382141656a Mon Sep 17 00:00:00 2001 From: simei94 Date: Thu, 16 May 2024 17:55:30 +0200 Subject: [PATCH] new approach to add bcycle infrastructure --- Makefile | 56 +++++------ .../network/CreateBikeNetworkFromShp.java | 96 +++++++++++++++++++ .../MexicoCitySumoNetworkConverter.java | 16 +--- .../org/matsim/run/RunMexicoCityScenario.java | 3 +- 4 files changed, 132 insertions(+), 39 deletions(-) create mode 100644 src/main/java/org/matsim/prepare/network/CreateBikeNetworkFromShp.java diff --git a/Makefile b/Makefile index f57c56f..171da30 100644 --- a/Makefile +++ b/Makefile @@ -85,45 +85,47 @@ input/sumo.net.xml: input/network.osm --osm.lane-access true\ --proj "+proj=utm +zone=12 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"\ -input/first-network.xml.gz: input/sumo.net.xml +input/first-network.xml.gz: input/sumo.net.xml ..\..\public-svn\matsim\scenarios\countries\mx\mexico-city\mexico-city-v1.0\input\data-scenario-generation\cycleways_semovi\ciclovias_cdmx_buffer_utm12n.shp - $(sc) prepare network-from-sumo-mexico-city $< --target-crs $(CRS) --output $@ + $(sc) --income-area "" prepare network-from-sumo-mexico-city $< --target-crs $(CRS) --output $@ - $(sc) prepare clean-network $@ --output $@ --modes car,ride,bike + $(sc) --income-area "" prepare bike-network-from-shp --network $@ --output $@ --shp $(word 2,$^) + + $(sc) --income-area "" prepare clean-network $@ --output $@ --modes car,ride,bike input/first-network-with-pt.xml.gz: input/first-network.xml.gz - $(sc) prepare transit-from-gtfs --network $<\ + $(sc) --income-area "" prepare transit-from-gtfs --network $<\ --output=input/\ --name $N-$V --date "2023-03-07" --target-crs $(CRS) \ ../../public-svn/matsim/scenarios/countries/mx/$N/$N-$V/input/data-scenario-generation/gtfs_semovi_2024-02-22.zip input/mexico-city-v1.0-transitVehicles_corrected.xml.gz: input/mexico-city-v1.0-transitVehicles.xml.gz - $(sc) prepare correct-pt-vehicle-types\ + $(sc) --income-area "" prepare correct-pt-vehicle-types\ --vehicles $< ############################################ 2) POPULATION CREATION ########################################################### input/first-population-cdmx-only-1pct-homeLocOnly.plans.xml.gz: ..\..\public-svn\matsim\scenarios\countries\mx\mexico-city\mexico-city-v1.0\input\data-scenario-generation/manzanas_censo2020\manzanas_censo2020_utm12n.shp - $(sc) prepare mexico-city-population\ + $(sc) --income-area "" prepare mexico-city-population\ --shp $<\ --output $@ input/first-population-zmvm-without-cdmx-1pct-homeLocOnly.plans.xml.gz: ..\..\public-svn\matsim\scenarios\countries\mx\mexico-city\mexico-city-v1.0\input\data-scenario-generation/zmvm_2010\zmvm_2010_utm12n.shp - $(sc) prepare zmvm-population\ + $(sc) --income-area "" prepare zmvm-population\ --input ..\..\public-svn\matsim\scenarios\countries\mx\mexico-city\mexico-city-v1.0\input\data-scenario-generation/iter_13_cpv2020\conjunto_de_datos\conjunto_de_datos_iter_13CSV20.csv,..\..\public-svn\matsim\scenarios\countries\mx\mexico-city\mexico-city-v1.0\input\data-scenario-generation/iter_15_cpv2020\conjunto_de_datos\conjunto_de_datos_iter_15CSV20.csv\ --shp $<\ --output $@ input/mexico-city-static-1pct.plans.xml.gz: input/first-population-cdmx-only-1pct-homeLocOnly.plans.xml.gz input/first-population-zmvm-without-cdmx-1pct-homeLocOnly.plans.xml.gz - $(sc) prepare merge-populations $^\ + $(sc) --income-area "" prepare merge-populations $^\ --output $@ # the activites and persons table for this class are created by sampling survey data. # this is done via matsim-python-tools: https://github.com/matsim-vsp/matsim-python-tools/blob/mexico-city/matsim/scenariogen/data/run_extract_activities.py input/mexico-city-activities-1pct.plans.xml.gz: input/mexico-city-static-1pct.plans.xml.gz - $(sc) prepare activity-sampling --input $<\ + $(sc) --income-area "" prepare activity-sampling --input $<\ --output $@\ --persons input/table-persons.csv.gz\ --activities input/table-activities.csv.gz\ @@ -131,13 +133,13 @@ input/mexico-city-activities-1pct.plans.xml.gz: input/mexico-city-static-1pct.pl --shp ../../public-svn/matsim/scenarios/countries/mx/mexico-city/mexico-city-v1.0/input/data-scenario-generation/distritos_eod2017_unam/DistritosEODHogaresZMVM2017_utm12n.shp input/v1.0/mexico-city-v1.0-facilities.xml.gz: input/v1.0/mexico-city-v1.0-network.xml.gz ../../public-svn/matsim/scenarios/countries/mx/mexico-city/mexico-city-v1.0/input/data-scenario-generation/economy_locations_zmvm_2017/economy_locations_zmvm_2017_utm12n.shp - $(sc) prepare facilities\ + $(sc) --income-area "" prepare facilities\ --network $<\ --shp $(word 2,$^)\ --output $@ input/commuter.csv: ../../public-svn/matsim/scenarios/countries/mx/mexico-city/mexico-city-v1.0/input/data-scenario-generation/data-input-eod2017-bundled/tviaje.csv - $(sc) prepare create-commute-relations\ + $(sc) --income-area "" prepare create-commute-relations\ --od-survey $<\ --zmvm-shp ../../public-svn/matsim/scenarios/countries/mx/mexico-city/mexico-city-v1.0/input/data-scenario-generation/zmvm_2010/zmvm_2010_utm12n.shp\ --survey-shp ../../public-svn/matsim/scenarios/countries/mx/mexico-city/mexico-city-v1.0/input/data-scenario-generation/distritos_eod2017_unam/DistritosEODHogaresZMVM2017_utm12n.shp\ @@ -145,7 +147,7 @@ input/commuter.csv: ../../public-svn/matsim/scenarios/countries/mx/mexico-city/m # --k 10 -> create 10 plans for each person to have more choices for CountOptimization input/mexico-city-initial-1pct.plans.xml.gz: input/mexico-city-activities-1pct.plans.xml.gz input/v1.0/mexico-city-v1.0-facilities.xml.gz input/v1.0/mexico-city-v1.0-network.xml.gz - $(sc) prepare init-location-choice\ + $(sc) --income-area "" prepare init-location-choice\ --input $<\ --output $@\ --facilities $(word 2,$^)\ @@ -155,19 +157,19 @@ input/mexico-city-initial-1pct.plans.xml.gz: input/mexico-city-activities-1pct.p --k 10\ # For debugging and visualization - $(sc) prepare downsample-population $@\ + $(sc) --income-area "" prepare downsample-population $@\ --sample-size 0.01\ --samples 0.001\ # create vehicle types input/mexico-city-v1.0-vehicle-types.xml: ./input - $(sc) prepare vehicle-types\ + $(sc) --income-area "" prepare vehicle-types\ --directory $<\ --modes car,bike # create count stations based on csv count data input/mexico-city-v1.0.counts_car.2017.xml: ../../public-svn/matsim/scenarios/countries/mx/mexico-city/mexico-city-v1.0/input/data-scenario-generation/counts input/v1.0/mexico-city-v1.0-network-with-pt.xml.gz input/v1.0/mexico-city-v1.0-network-linkGeometries.csv - $(sc) prepare counts\ + $(sc) --income-area "" prepare counts\ --input $<\ --network $(word 2,$^)\ --network-geometries $(word 3,$^)\ @@ -176,12 +178,12 @@ input/mexico-city-v1.0.counts_car.2017.xml: ../../public-svn/matsim/scenarios/co --manual-matched-counts input/manualLinkAssignment.csv\ --year 2017 - $(sc) prepare scale-counts\ + $(sc) --income-area "" prepare scale-counts\ --input $@ # create first scenario specific config input/mexico-city-v1.0-1pct.input.config.xml: ./input/v1.0 ./input - $(sc) prepare config\ + $(sc) --income-area "" prepare config\ --input-directory $<\ --modes car,bike,pt,walk,taxibus\ --output-directory $(word 2,$^) @@ -198,7 +200,7 @@ input/eval-opt: # experienced plans are output of above calibration eval run ERROR_METRIC ?= LOG_ERROR input/mexico-city-initial-1pct-plan-selection.csv: ./input/mexico-city-initial-1.0-1pct.experienced_plans.xml.gz input/v1.0/mexico-city-v1.0-network.xml.gz input/v1.0/mexico-city-v1.0.counts_car.2017.xml - $(sc) prepare run-count-opt\ + $(sc) --income-area "" prepare run-count-opt\ --input $<\ --network $(word 2,$^)\ --counts $(word 3,$^)\ @@ -207,48 +209,48 @@ input/mexico-city-initial-1pct-plan-selection.csv: ./input/mexico-city-initial-1 --k 10 input/mexico-city-initial-1pct.LOG_ERROR.plans.xml.gz: input/v1.0/mexico-city-initial-1pct.plans.xml.gz input/mexico-city-initial-1pct-plan-selection.csv - $(sc) prepare select-plans-idx\ + $(sc) --income-area "" prepare select-plans-idx\ --input $<\ --csv $(word 2,$^)\ --output $@\ --exp-plans input/mexico-city-initial-1.0-1pct.experienced_plans.xml.gz input/v1.0/mexico-city-v1.0-1pct.input.plans.xml.gz: input/v1.0/mexico-city-initial-1pct.LOG_ERROR.plans.xml.gz - $(sc) prepare split-activity-types-duration\ + $(sc) --income-area "" prepare split-activity-types-duration\ --input $<\ --output $@ - $(sc) prepare change-mode-names\ + $(sc) --income-area "" prepare change-mode-names\ --input $@\ --output $@ - $(sc) prepare check-car-avail\ + $(sc) --income-area "" prepare check-car-avail\ --input $@\ --output $@\ --mode walk - $(sc) prepare fix-subtour-modes\ + $(sc) --income-area "" prepare fix-subtour-modes\ --input $@\ --output $@\ --all-plans\ --coord-dist 100 # commented out due to bug when reading plans / activities with assigned facilityIds, see matsim-libs PR3106 -# $(sc) prepare xy-to-links\ +# $(sc) --income-area "" prepare xy-to-links\ # --network input/v1.0/mexico-city-v1.0-network.xml.gz\ # --input $@\ # --output $@ - $(sc) prepare extract-home-coordinates $@\ + $(sc) --income-area "" prepare extract-home-coordinates $@\ --csv input/v1.0/mexico-city-v1.0-homes.csv - $(sc) prepare downsample-population $@\ + $(sc) --income-area "" prepare downsample-population $@\ --sample-size 0.01\ --samples 0.001\ # this step does not fully work yet, because some activities do not have a coord yet -> see comments on prepare xy-to-links check: input/v1.0/mexico-city-v1.0-1pct.input.plans.xml.gz - $(sc) analysis check-population $<\ + $(sc) --income-area "" analysis check-population $<\ --input-crs $(CRS)\ --shp ../../public-svn/matsim/scenarios/countries/mx/mexico-city/mexico-city-v1.0/input/data-scenario-generation/zmvm_2010/zmvm_2010_utm12n.shp\ --shp-crs $(CRS) diff --git a/src/main/java/org/matsim/prepare/network/CreateBikeNetworkFromShp.java b/src/main/java/org/matsim/prepare/network/CreateBikeNetworkFromShp.java new file mode 100644 index 0000000..2327398 --- /dev/null +++ b/src/main/java/org/matsim/prepare/network/CreateBikeNetworkFromShp.java @@ -0,0 +1,96 @@ +package org.matsim.prepare.network; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.locationtech.jts.geom.Geometry; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.application.MATSimAppCommand; +import org.matsim.application.options.ShpOptions; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.network.algorithms.MultimodalNetworkCleaner; +import org.matsim.core.utils.geometry.geotools.MGC; +import org.opengis.feature.simple.SimpleFeature; +import picocli.CommandLine; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +@CommandLine.Command( + name = "bike-network-from-shp", + description = "Add bike as a network mode to network links. Based on a shp file with cycleways." +) +public class CreateBikeNetworkFromShp implements MATSimAppCommand { + @CommandLine.Option(names = "--network", description = "Path to input network file.", required = true) + private Path inputNetwork; + @CommandLine.Option(names = "--output", description = "Output xml file", required = true) + private Path output; + @CommandLine.Mixin + private final ShpOptions shp = new ShpOptions(); + + private final Logger log = LogManager.getLogger(CreateBikeNetworkFromShp.class); + + public static void main(String[] args) { + new CreateBikeNetworkFromShp().execute(args); + } + + @Override + public Integer call() throws Exception { +// shp file has to be provided + if (!shp.isDefined()) { + log.error("No shp file is provided. It is required to provide a shp file with cycleways via --shp!"); + return 2; + } + + List geometries = new ArrayList<>(); + for (SimpleFeature feature : shp.readFeatures()) { + geometries.add((Geometry) feature.getDefaultGeometry()); + } + + Network network = NetworkUtils.readNetwork(inputNetwork.toString()); + + log.info("Starting to adapt the network, this might take a while!"); + + int count = 0; + for (Link link : network.getLinks().values()) { + + boolean fromInside = false; + boolean toInside = false; + + for (Geometry geom : geometries) { + if (!fromInside) { + fromInside = MGC.coord2Point(link.getFromNode().getCoord()).within(geom); + } + + if (!toInside) { + toInside = MGC.coord2Point(link.getToNode().getCoord()).within(geom); + } + +// if to and from node are inside of _any_ cycleway shape we want to add bike as allowed mode. +// if we check isInside = MGC.coord2Point(link.getFromNode().getCoord()).within(geom) && MGC.coord2Point(link.getToNode().getCoord()).within(geom) +// for only one geometry at a time there are many holes, which leads to big parts of the bike net being "cleaned out" -sme0524 + if (fromInside && toInside && !link.getAttributes().getAttribute("type").toString().contains("highway.motorway")) { + Set modes = new HashSet<>(); + modes.add(TransportMode.bike); + modes.addAll(link.getAllowedModes()); + link.setAllowedModes(modes); + count++; + break; + } + } + } + + log.info("For {} links bike was added as an allowed mode.", count); + MultimodalNetworkCleaner cleaner = new MultimodalNetworkCleaner(network); + cleaner.run(Set.of(TransportMode.bike)); + + NetworkUtils.writeNetwork(network, output.toString()); + log.info("Output network has been written to {}.", output); + + return 0; + } +} diff --git a/src/main/java/org/matsim/prepare/network/MexicoCitySumoNetworkConverter.java b/src/main/java/org/matsim/prepare/network/MexicoCitySumoNetworkConverter.java index be253d3..d805eb4 100644 --- a/src/main/java/org/matsim/prepare/network/MexicoCitySumoNetworkConverter.java +++ b/src/main/java/org/matsim/prepare/network/MexicoCitySumoNetworkConverter.java @@ -271,23 +271,17 @@ public MexicoCitySumoNetworkHandler convert(Network network, Lanes lanes) throws MexicoCitySumoNetworkHandler.Type type = sumoHandler.types.get(edge.type); -// TODO: implement solution to only add bike if there is a lane for bikes. therefore, check if lane.allow has bike or lane.disallow doesnt have it -// may be easier to add bike here and afterwards delete it from set -// therefore link.setAllowedModes has to be called after for loop through lanes -// if not used -> BIKE ONLY LANES HAVE TO BE IGNORED IN THE BELOW FOR LOOP!! - - if (type.allow.contains("bicycle") || (type.allow.isEmpty() && !type.disallow.contains("bicycle"))) - modes.add(TransportMode.bike); +// bike will not be added as allowed mode here. This happens in a separate step, see Makefile. -sme0524 link.setAllowedModes(modes); link.setLength(edge.getLength()); LanesToLinkAssignment l2l = lf.createLanesToLinkAssignment(link.getId()); for (MexicoCitySumoNetworkHandler.Lane lane : edge.lanes) { - if ((lane.allow.contains("bus") && lane.allow.size() == 1) || (lane.allow.contains("bicycle") && lane.allow.size() == 1)) { -// if only bus or bike is allowed on lane -> lane does not count as an accessible lane, pt is added as a separate network later -sme0324 - link.setNumberOfLanes(link.getNumberOfLanes() - 1); - continue; + if ((lane.allow.contains("bus") && lane.allow.size() == 1)) { +// if only bus is allowed on lane -> lane does not count as an accessible lane, pt is added as a separate network later -sme0324 + link.setNumberOfLanes(link.getNumberOfLanes() - 1); + continue; } Lane mLane = lf.createLane(Id.create(lane.id, Lane.class)); mLane.setAlignment(lane.index); diff --git a/src/main/java/org/matsim/run/RunMexicoCityScenario.java b/src/main/java/org/matsim/run/RunMexicoCityScenario.java index 86a36a9..09ab470 100644 --- a/src/main/java/org/matsim/run/RunMexicoCityScenario.java +++ b/src/main/java/org/matsim/run/RunMexicoCityScenario.java @@ -34,6 +34,7 @@ import org.matsim.core.router.AnalysisMainModeIdentifier; import org.matsim.core.scoring.functions.ScoringParametersForPerson; import org.matsim.prepare.*; +import org.matsim.prepare.network.CreateBikeNetworkFromShp; import org.matsim.prepare.network.CreateMexicoCityNetworkFromSumo; import org.matsim.prepare.network.PrepareNetwork; import org.matsim.prepare.opt.RunCountOptimization; @@ -55,7 +56,7 @@ @CommandLine.Command(header = ":: Open Mexico-City Scenario ::", version = RunMexicoCityScenario.VERSION, mixinStandardHelpOptions = true) @MATSimApplication.Prepare({ AdaptCountsScale.class, AdjustActivityToLinkDistances.class, ChangeFacilities.class, ChangeModeNames.class, CheckActivityFacilities.class, CheckCarAvailability.class, CleanNetwork.class, CorrectPtVehicleTypes.class, - CreateCommuterRelations.class, CreateCountsFromDatosVialesPortal.class, CreateLandUseShp.class, CreateMATSimFacilities.class, CreateMetropolitanAreaPopulation.class, + CreateBikeNetworkFromShp.class, CreateCommuterRelations.class, CreateCountsFromDatosVialesPortal.class, CreateLandUseShp.class, CreateMATSimFacilities.class, CreateMetropolitanAreaPopulation.class, CreateMexicoCityPopulation.class, CreateMexicoCityScenarioConfig.class, CreateMexicoCityNetworkFromSumo.class, CreateTransitScheduleFromGtfs.class, CreateVehicleTypes.class, DownSamplePopulation.class, ExtractHomeCoordinates.class, FixSubtourModes.class, GenerateShortDistanceTrips.class, InitLocationChoice.class, MergePopulations.class, PrepareBikePopulation.class, PrepareIncome.class, PrepareNetwork.class, ResolveGridCoordinates.class, RunActivitySampling.class, RunCountOptimization.class,